summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/presentation-api/receiving-ua/PresentationReceiver_create-manual.https.html
diff options
context:
space:
mode:
Diffstat (limited to 'testing/web-platform/tests/presentation-api/receiving-ua/PresentationReceiver_create-manual.https.html')
-rw-r--r--testing/web-platform/tests/presentation-api/receiving-ua/PresentationReceiver_create-manual.https.html272
1 files changed, 272 insertions, 0 deletions
diff --git a/testing/web-platform/tests/presentation-api/receiving-ua/PresentationReceiver_create-manual.https.html b/testing/web-platform/tests/presentation-api/receiving-ua/PresentationReceiver_create-manual.https.html
new file mode 100644
index 0000000000..96fc6f345d
--- /dev/null
+++ b/testing/web-platform/tests/presentation-api/receiving-ua/PresentationReceiver_create-manual.https.html
@@ -0,0 +1,272 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Creating a receiving browsing context</title>
+<link rel="author" title="Tomoyuki Shimizu" href="https://github.com/tomoyukilabs">
+<link rel="help" href="https://w3c.github.io/presentation-api/#creating-a-receiving-browsing-context">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="common.js"></script>
+<script src="support/stash.js"></script>
+
+<p id="notice">
+ Click the button below and select the available presentation display, to start the manual test. The test passes if a "PASS" result appears.<br>
+ This test asks you to click the button twice, unless the test fails.<br>
+ <button id="presentBtn">Start Presentation Test</button>
+</p>
+
+<script>
+ setup({explicit_timeout: true});
+
+ let receiverStack;
+ add_completion_callback(() => {
+ // overwrite a stack written in the test result
+ if (receiverStack) {
+ document.querySelector('#log pre').textContent = receiverStack;
+ }
+ });
+
+ let connection;
+ const presentBtn = document.getElementById('presentBtn');
+
+ const dbName = {
+ controller: 'db-presentation-api-controlling-ua',
+ receiver: 'db-presentation-api-receiving-ua'
+ };
+
+ const main = () => {
+ promise_test(t => {
+ presentBtn.disabled = true;
+ const stash = new Stash(stashIds.toController, stashIds.toReceiver);
+ const request = new PresentationRequest('support/PresentationReceiver_create_receiving-ua.html');
+
+ t.add_cleanup(() => {
+ const notice = document.getElementById('notice');
+ notice.parentNode.removeChild(notice);
+ stash.stop();
+
+ // history.back();
+ document.cookie = 'PresentationApiTest=true; Expires=' + new Date().toUTCString();
+ sessionStorage.removeItem('presentation_api_test');
+ localStorage.removeItem('presentation_api_test');
+
+ Object.values(dbName).forEach(name => {
+ indexedDB.deleteDatabase(name);
+ });
+
+ if (connection) {
+ connection.onconnect = () => { connection.terminate(); };
+ if (connection.state === 'closed')
+ request.reconnect(connection.id);
+ else
+ connection.terminate();
+ }
+
+ if ('serviceWorker' in navigator) {
+ navigator.serviceWorker.getRegistrations().then(registrations => {
+ return Promise.all(registrations.map(reg => reg.unregister()));
+ });
+ }
+ if ('caches' in window) {
+ caches.keys().then(keys => {
+ return Promise.all(keys.map(key => caches.delete(key)));
+ });
+ }
+ });
+
+ history.pushState(null, 'test', 'PresentationReceiver_create-manual.https.html');
+ document.cookie = 'PresentationApiTest=Controlling-UA';
+
+ const storageName = 'presentation_api_test';
+ const storageValue = 'receiving-ua';
+ sessionStorage.setItem(storageName, storageValue);
+ localStorage.setItem(storageName, storageValue);
+
+ const openIndexedDB = () => {
+ if ('indexedDB' in window) {
+ const req = indexedDB.open(dbName.controller, 1);
+ const eventWatcher = new EventWatcher(t, req, 'upgradeneeded');
+ return eventWatcher.wait_for('upgradeneeded').then(evt => {
+ evt.target.result.close();
+ });
+ }
+ else
+ return Promise.resolve();
+ };
+
+ const cacheName = 'controlling-ua';
+ let clientUrls;
+ const getClientUrls = () => {
+ return new Promise(resolve => {
+ navigator.serviceWorker.getRegistration().then(reg => {
+ if (reg) {
+ const channel = new MessageChannel();
+ channel.port1.onmessage = event => {
+ resolve(event.data);
+ };
+ reg.active.postMessage('', [channel.port2]);
+ }
+ else
+ resolve([]);
+ });
+ });
+ };
+ const registerServiceWorker = () => {
+ return ('serviceWorker' in navigator ?
+ navigator.serviceWorker.register('serviceworker.js').then(registration => {
+ return new Promise((resolve, reject) => {
+ if (registration.installing) {
+ registration.installing.addEventListener('statechange', event => {
+ if(event.target.state === 'installed')
+ resolve();
+ });
+ }
+ else
+ resolve();
+ });
+ }) : Promise.resolve()).then(getClientUrls).then(urls => {
+ clientUrls = urls;
+ });
+ };
+ const openCaches = () => {
+ return 'caches' in window ? caches.open(cacheName).then(cache => cache.add('cache.txt')) : Promise.resolve();
+ };
+
+ const checkUpdates = () => {
+ // Cookie
+ assert_equals(document.cookie, 'PresentationApiTest=Controlling-UA', 'A cookie store is not shared with a receiving user agent.');
+
+ // Web Storage
+ assert_equals(sessionStorage.length, 1, 'Session storage is not shared with a receiving user agent.');
+ assert_equals(sessionStorage.getItem(storageName), storageValue, 'Session storage is not shared with a receiving user agent.');
+ assert_equals(localStorage.length, 1, 'Local storage is not shared with a receiving user agent.');
+ assert_equals(localStorage.getItem(storageName), storageValue, 'Local storage is not shared with a receiving user agent.');
+ };
+
+ // Indexed Database
+ const checkIndexedDB = t => {
+ if ('indexedDB' in window) {
+ const req = indexedDB.open(dbName.receiver);
+ const upgradeneededWatcher = new EventWatcher(t, req, 'upgradeneeded');
+ const successWatcher = new EventWatcher(t, req, 'success');
+ return Promise.race([
+ upgradeneededWatcher.wait_for('upgradeneeded').then(evt => {
+ evt.target.result.close();
+ }),
+ successWatcher.wait_for('success').then(evt => {
+ evt.target.result.close();
+ // This would fail if the database created by the receiving UA is visible to the controlling UA
+ assert_unreached('Indexed Database is not shared with a receiving user agent.');
+ })
+ ]);
+ }
+ else
+ return Promise.resolve();
+ };
+
+ // Service Workers
+ const checkServiceWorkers = () => {
+ return 'serviceWorker' in navigator ? navigator.serviceWorker.getRegistrations().then(registrations => {
+ const message = 'List of registered service worker registrations is not shared with a receiving user agent.';
+ assert_equals(registrations.length, 1, message);
+ assert_equals(registrations[0].active.scriptURL, new Request('serviceworker.js').url, message);
+ }) : Promise.resolve();
+ };
+ const checkCaches = () => {
+ const message = 'Cache storage is not shared with a receiving user agent.';
+ return 'caches' in window ? caches.keys().then(keys => {
+ assert_equals(keys.length, 1, message);
+ assert_equals(keys[0], cacheName, message);
+ return caches.open(keys[0]);
+ }).then(cache => cache.matchAll())
+ .then(responses => {
+ assert_equals(responses.length, 1, message);
+ assert_equals(responses[0].url, new Request('cache.txt').url, message);
+ }) : Promise.resolve();
+ };
+
+ let timeout;
+ const enableTimeout = () => {
+ timeout = t.step_timeout(() => {
+ t.force_timeout();
+ t.done();
+ }, 5000);
+ };
+ const disableTimeout = () => {
+ clearTimeout(timeout);
+ };
+ const cancelWait = () => {
+ connection.removeEventListener('close', onTerminate);
+ connection.removeEventListener('terminate', onTerminate);
+ };
+ const onTerminate = (reject, event) => {
+ cancelWait();
+ reject('A receiving user agent unexpectedly ' + event.type + 'd a presentation. ');
+ };
+ const waitForTerminate = () => {
+ return new Promise((resolve, reject) => {
+ connection.addEventListener('close', onTerminate.bind(this, reject));
+ connection.addEventListener('terminate', onTerminate.bind(this, reject));
+ });
+ };
+
+ // Start a presentation for receiving user agent tests
+ return request.start().then(c => {
+ connection = c;
+ enableTimeout();
+
+ // This Promise.race will be rejected if a receiving side terminates/closes the connection when window.close() is invoked
+ return Promise.race([
+ openIndexedDB()
+ .then(registerServiceWorker)
+ .then(openCaches)
+ .then(() => { return stash.init(); })
+ .then(() => { return stash.receive(); }),
+ waitForTerminate()]);
+ }).then(result => {
+ // terminate and connect again if the result is PASS
+ cancelWait();
+ const json = JSON.parse(result);
+ if (json.test.status !== 0)
+ return json;
+
+ // 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.');
+ const eventWatcher = new EventWatcher(t, connection, 'terminate');
+ connection.terminate();
+ return eventWatcher.wait_for('terminate');
+ }).then(() => {
+ connection = null;
+ disableTimeout();
+ presentBtn.removeEventListener('click', main);
+ presentBtn.textContent = 'Continue Presentation Test';
+ presentBtn.disabled = false;
+ const eventWatcher = new EventWatcher(t, presentBtn, 'click');
+ return eventWatcher.wait_for('click');
+ }).then(() => {
+ presentBtn.disabled = true;
+ return request.start();
+ }).then(c => {
+ connection = c;
+ enableTimeout();
+ return stash.receive();
+ }).then(result => {
+ return JSON.parse(result);
+ });
+ }).then(json => {
+ if (json.test.status === 0) {
+ checkUpdates();
+ return checkIndexedDB(t)
+ .then(checkServiceWorkers)
+ .then(checkCaches);
+ }
+ else {
+ receiverStack = json.test.stack;
+ parseResult(json.test.message);
+ }
+ });
+ });
+ };
+ presentBtn.addEventListener('click', main);
+</script>