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
|
<!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>
<p id="notice">Checking <code id="modal"></code>: if you see this message, please wait for test to time out.</p>
<script>
add_completion_callback((tests, status) => {
// remove unserializable attributes, then send the result to the parent window
// note: a single test result is supposed to appear here.
window.parent.postMessage(JSON.parse(JSON.stringify({
type: 'presentation-api', test: tests[0], status: status
})), location.origin);
});
window.addEventListener('message', event => {
if(event.data !== 'start')
return;
promise_test(t => {
const notice = document.getElementById('notice');
const modal = document.getElementById('modal');
// Presentation and PresentationReceiver
assert_true(navigator.presentation instanceof Presentation, 'navigator.presentation in a nested browsing context is an instanceof Presentation.');
assert_equals(navigator.presentation.receiver, null, 'navigator.presentation.receiver in a nested browsing context is set to null.');
// Session history
assert_equals(window.history.length, 1, 'Session history consists of the current page only.');
// The Sandboxed auxiliary navigation browsing context flag (codes below are expected to be ignored)
assert_equals(window.open('./idlharness_receiving-ua.html'), null, 'Sandboxed auxiliary navigation browsing context flag is set.');
// The sandboxed modals flag (codes below are expected to be ignored):
// If user agent prompts user, a timeout will occur and the test will eventually fail
let message = 'If you see this prompt, do not dismiss it and wait for test to time out.';
notice.style.display = 'block';
modal.textContent = 'alert()';
alert(message);
modal.textContent = 'confirm()';
confirm(message);
modal.textContent = 'print()';
print();
modal.textContent = 'prompt()';
prompt(message);
notice.style.display = 'none';
// Permissions
const checkPermission = query => {
return navigator.permissions ? navigator.permissions.query(query).then(status => {
assert_equals(status.state, 'denied', 'The state of the "' + query.name + '" permission in a nested browsing context is set to "denied".');
}, () => { /* skip this assertion if the specified permission is not implemented */ }) : Promise.resolve();
};
// Cookie
assert_equals(document.cookie, 'PresentationApiTest=Receiving-UA', 'A cookie store is shared by top-level and nested browsing contexts.');
// Indexed Database
const dbName = 'db-presentation-api-receiving-ua';
const checkIndexedDB = () => {
if ('indexedDB' in window) {
message = 'Indexed Database is shared by top-level and nested browsing contexts.';
const req = indexedDB.open(dbName);
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();
// This would fail if the database is not created by the top-level browsing context
assert_unreached(message);
}),
successWatcher.wait_for('success').then(evt => {
evt.target.result.close();
const db = evt.target.result;
const version = db.version;
db.close();
// Check if the version of the database is 2 as specified by the top-level browsing context
assert_equals(version, 2, message);
// Upgrade the version
const req = indexedDB.open(dbName, 3);
const eventWatcher = new EventWatcher(t, req, 'upgradeneeded');
return eventWatcher.wait_for('upgradeneeded');
}).then(evt => {
evt.target.result.close();
})
]);
}
else
return Promise.resolve();
};
// Web Storage
assert_equals(sessionStorage.length, 1, 'Session storage is shared by top-level and nested browsing contexts.');
assert_equals(sessionStorage.getItem('presentation_api_test'), 'receiving-ua', 'Session storage is shared by top-level and nested browsing contexts.');
assert_equals(localStorage.length, 1, 'Local storage is shared by top-level and nested browsing contexts.');
assert_equals(localStorage.getItem('presentation_api_test'), 'receiving-ua', 'Local storage is shared by top-level and nested browsing contexts.');
// Service Workers
const checkServiceWorkers = () => {
return 'serviceWorker' in navigator ? navigator.serviceWorker.getRegistrations().then(registrations => {
message = 'List of registered service worker registrations is shared by top-level and nested browsing contexts.';
assert_equals(registrations.length, 1, message);
assert_equals(registrations[0].active.scriptURL, new Request('../serviceworker.js').url, message);
}) : Promise.resolve();
};
const checkCaches = () => {
message = 'Cache storage is shared by top-level and nested browsing contexts.';
return 'caches' in window ? caches.keys().then(keys => {
assert_equals(keys.length, 1, message);
assert_equals(keys[0], 'receiving-ua', 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();
};
// Update storages and service workers shared with the top-level brosing context
document.cookie = 'NestedBrowsingContext=True';
sessionStorage.setItem('nested_browsing_context', 'yes');
localStorage.setItem('nested_browsing_context', 'yes');
// register a service worker with different scope from that of the top-level browsing context
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();
};
const openCaches = () => {
return 'caches' in window
? caches.open('nested-browsing-context').then(cache => cache.add('../cache.txt')) : Promise.resolve();
};
// Asynchronous tests
const permissionList = [
{ name: 'geolocation' },
{ name: 'notifications' },
{ name: 'push', userVisibleOnly: true },
{ name: 'midi' },
{ name: 'camera' },
{ name: 'microphone' },
{ name: 'speaker' },
{ name: 'background-sync' }
];
return Promise.all(permissionList.map(perm => { return checkPermission(perm); }))
.then(checkIndexedDB)
.then(checkServiceWorkers)
.then(checkCaches)
.then(registerServiceWorker)
.then(openCaches);
});
});
</script>
|