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
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
|
<!doctype html>
<meta name=variant content="?dialog">
<meta name=variant content="?CloseWatcher">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/resources/testdriver.js"></script>
<script src="/resources/testdriver-vendor.js"></script>
<script src="/resources/testdriver-actions.js"></script>
<script src="/common/top-layer.js"></script>
<script src="resources/helpers.js"></script>
<body>
<script>
const type = location.search.substring(1);
const waitForPotentialCloseEvent = () => {
// CloseWatchers fire close events synchronously, but dialog elements wait
// for a rAF before firing them.
return new Promise(resolve => requestAnimationFrame(resolve));
};
promise_test(async t => {
const events = [];
const freeWatcher = createRecordingCloseWatcher(t, events, "freeWatcher", type);
freeWatcher.addEventListener("cancel", e => e.preventDefault());
await maybeTopLayerBless(freeWatcher);
freeWatcher.close();
await waitForPotentialCloseEvent();
assert_array_equals(events, ["freeWatcher close"]);
}, "Close watchers created without user activation, but close()d via user activation, do not fire cancel");
promise_test(async t => {
const events = [];
const freeWatcher = createRecordingCloseWatcher(t, events, "freeWatcher", type);
await maybeTopLayerBless(freeWatcher);
await sendCloseRequest();
await waitForPotentialCloseEvent();
assert_array_equals(events, ["freeWatcher cancel", "freeWatcher close"]);
}, "Close watchers created without user activation, but closed via a close request after user activation, fires cancel");
promise_test(async t => {
const events = [];
const freeWatcher = createRecordingCloseWatcher(t, events, "freeWatcher", type);
freeWatcher.addEventListener("cancel", e => e.preventDefault());
await maybeTopLayerBless(freeWatcher);
await sendCloseRequest();
await waitForPotentialCloseEvent();
assert_array_equals(events, ["freeWatcher cancel"]);
}, "Close watchers created without user activation, but closed via a close request after user activation, fires cancel, which can be preventDefault()ed");
promise_test(async t => {
const events = [];
createRecordingCloseWatcher(t, events, "freeWatcher", type);
createRecordingCloseWatcher(t, events, "watcher1", type);
createRecordingCloseWatcher(t, events, "watcher2", type);
await sendCloseRequest();
await waitForPotentialCloseEvent();
assert_array_equals(events, ["watcher2 close", "watcher1 close", "freeWatcher close"]);
}, "Multiple close watchers created without user activation close together (with no cancel)");
promise_test(async t => {
const events = [];
const freeWatcher = createRecordingCloseWatcher(t, events, "freeWatcher", type);
await createBlessedRecordingCloseWatcher(t, events, "activationWatcher", type, freeWatcher);
await sendCloseRequest();
await waitForPotentialCloseEvent();
assert_array_equals(events, ["activationWatcher close"]);
await sendCloseRequest();
await waitForPotentialCloseEvent();
assert_array_equals(events, ["activationWatcher close", "freeWatcher close"]);
}, "Creating a close watcher from user activation keeps it separate from the free close watcher, but they don't fire cancel");
promise_test(async t => {
const events = [];
const freeWatcher = createRecordingCloseWatcher(t, events, "freeWatcher", type);
const activationWatcher = await createBlessedRecordingCloseWatcher(t, events, "activationWatcher", type, freeWatcher);
await maybeTopLayerBless(activationWatcher);
await sendCloseRequest();
await waitForPotentialCloseEvent();
assert_array_equals(events, ["activationWatcher cancel", "activationWatcher close"]);
await maybeTopLayerBless(freeWatcher);
await sendCloseRequest();
await waitForPotentialCloseEvent();
assert_array_equals(events, ["activationWatcher cancel", "activationWatcher close", "freeWatcher cancel", "freeWatcher close"]);
}, "Creating a close watcher from user activation, and closing close watchers with a close request after user activation, fires cancel");
promise_test(async t => {
const events = [];
const freeWatcher = createRecordingCloseWatcher(t, events, "freeWatcher", type);
const activationWatcher1 = await createBlessedRecordingCloseWatcher(t, events, "activationWatcher1", type, freeWatcher);
await createBlessedRecordingCloseWatcher(t, events, "activationWatcher2", type, activationWatcher1);
await sendCloseRequest();
await waitForPotentialCloseEvent();
assert_array_equals(events, ["activationWatcher2 close"]);
await sendCloseRequest();
await waitForPotentialCloseEvent();
assert_array_equals(events, ["activationWatcher2 close", "activationWatcher1 close"]);
}, "Multiple close watchers created with user activation close in reverse order");
promise_test(async t => {
const events = [];
const freeWatcher = createRecordingCloseWatcher(t, events, "freeWatcher", type);
const activationWatcher1 = await createBlessedRecordingCloseWatcher(t, events, "activationWatcher1", type, freeWatcher);
const activationWatcher2 = await createBlessedRecordingCloseWatcher(t, events, "activationWatcher2", type, activationWatcher1);
await createBlessedRecordingCloseWatcher(t, events, "activationWatcher3", type, activationWatcher2);
createRecordingCloseWatcher(t, events, "watcher4", type);
await sendCloseRequest();
await waitForPotentialCloseEvent();
assert_array_equals(events, ["watcher4 close", "activationWatcher3 close"]);
await sendCloseRequest();
await waitForPotentialCloseEvent();
assert_array_equals(events, ["watcher4 close", "activationWatcher3 close", "activationWatcher2 close"]);
await sendCloseRequest();
await waitForPotentialCloseEvent();
assert_array_equals(events, ["watcher4 close", "activationWatcher3 close", "activationWatcher2 close", "activationWatcher1 close"]);
await sendCloseRequest();
await waitForPotentialCloseEvent();
assert_array_equals(events, ["watcher4 close", "activationWatcher3 close", "activationWatcher2 close", "activationWatcher1 close", "freeWatcher close"]);
}, "3 user activations let you have 3 + 1 = 4 ungrouped close watchers/0 cancel events");
promise_test(async t => {
const events = [];
const freeWatcher1 = createRecordingCloseWatcher(t, events, "freeWatcher1", type);
await sendCloseRequest();
await waitForPotentialCloseEvent();
assert_array_equals(events, ["freeWatcher1 close"]);
const freeWatcher2 = createRecordingCloseWatcher(t, events, "freeWatcher2", type);
await sendCloseRequest();
await waitForPotentialCloseEvent();
assert_array_equals(events, ["freeWatcher1 close", "freeWatcher2 close"]);
}, "closing the free close watcher via a close request allows a new free one to be created without user activation, and it receives a second close request");
promise_test(async t => {
const events = [];
const activationWatcher = await createBlessedRecordingCloseWatcher(t, events, "activationWatcher", type);
const freeWatcher = createRecordingCloseWatcher(t, events, "freeWatcher", type);
await sendCloseRequest();
await waitForPotentialCloseEvent();
assert_array_equals(events, ["freeWatcher close"]);
await sendCloseRequest();
await waitForPotentialCloseEvent();
assert_array_equals(events, ["freeWatcher close", "activationWatcher close"]);
}, "The second watcher can be the free watcher, if the first is created with user activation");
promise_test(async t => {
const events = [];
const activationWatcher1 = await createBlessedRecordingCloseWatcher(t, events, "activationWatcher1", type);
const activationWatcher2 = await createBlessedRecordingCloseWatcher(t, events, "activationWatcher2", type, activationWatcher1);
const freeWatcher = createRecordingCloseWatcher(t, events, "freeWatcher", type);
await sendCloseRequest();
await waitForPotentialCloseEvent();
assert_array_equals(events, ["freeWatcher close"]);
await sendCloseRequest();
await waitForPotentialCloseEvent();
assert_array_equals(events, ["freeWatcher close", "activationWatcher2 close"]);
await sendCloseRequest();
await waitForPotentialCloseEvent();
assert_array_equals(events, ["freeWatcher close", "activationWatcher2 close", "activationWatcher1 close"]);
}, "The third watcher can be the free watcher, if the first two are created with user activation");
promise_test(async t => {
const events = [];
const freeWatcher1 = createRecordingCloseWatcher(t, events, "freeWatcher1");
if (freeWatcher1 instanceof HTMLDialogElement) {
freeWatcher1.close();
} else {
freeWatcher1.destroy();
}
assert_array_equals(events, []);
const freeWatcher2 = createRecordingCloseWatcher(t, events, "freeWatcher2");
await sendCloseRequest();
assert_array_equals(events, ["freeWatcher2 close"]);
}, "destroy()ing the free close watcher allows a new free one to be created without user activation, and it receives the close request");
</script>
|