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
|
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const DOC = toDataURL("<div>foo</div>");
const DOC_IFRAME_MULTI = toDataURL(`
<iframe src='data:text/html,foo'></iframe>
<iframe src='data:text/html,bar'></iframe>
`);
const DOC_IFRAME_NESTED = toDataURL(`
<iframe src="${DOC_IFRAME_MULTI}"></iframe>
`);
// Disable bfcache to force documents to be destroyed on navigation
Services.prefs.setIntPref("browser.sessionhistory.max_total_viewers", 0);
registerCleanupFunction(() => {
Services.prefs.clearUserPref("browser.sessionhistory.max_total_viewers");
});
add_task(async function noEventWhenPageDomainDisabled({ client }) {
info("Navigate to a page with nested iframes");
await loadURL(DOC_IFRAME_NESTED);
await runFrameDetachedTest(client, 0, async () => {
info("Navigate away from a page with an iframe");
await loadURL(DOC);
});
});
add_task(async function noEventAfterPageDomainDisabled({ client }) {
const { Page } = client;
info("Navigate to a page with nested iframes");
await loadURL(DOC_IFRAME_NESTED);
await Page.enable();
await Page.disable();
await runFrameDetachedTest(client, 0, async () => {
info("Navigate away to a page with no iframes");
await loadURL(DOC);
});
});
add_task(async function noEventWhenNavigatingWithNoFrames({ client }) {
const { Page } = client;
await Page.enable();
info("Navigate to a page with no iframes");
await loadURL(DOC);
await runFrameDetachedTest(client, 0, async () => {
info("Navigate away to a page with no iframes");
await loadURL(DOC);
});
});
add_task(async function eventWhenNavigatingWithFrames({ client }) {
const { Page } = client;
info("Navigate to a page with iframes");
await loadURL(DOC_IFRAME_MULTI);
await Page.enable();
await runFrameDetachedTest(client, 2, async () => {
info("Navigate away to a page with no iframes");
await loadURL(DOC);
});
});
add_task(async function eventWhenNavigatingWithNestedFrames({ client }) {
const { Page } = client;
info("Navigate to a page with nested iframes");
await loadURL(DOC_IFRAME_NESTED);
await Page.enable();
await runFrameDetachedTest(client, 3, async () => {
info("Navigate away to a page with no iframes");
await loadURL(DOC);
});
});
add_task(async function eventWhenDetachingFrame({ client }) {
const { Page } = client;
info("Navigate to a page with iframes");
await loadURL(DOC_IFRAME_MULTI);
await Page.enable();
await runFrameDetachedTest(client, 1, async () => {
// Remove the single frame from the page
await SpecialPowers.spawn(gBrowser.selectedBrowser, [], () => {
const frame = content.document.getElementsByTagName("iframe")[0];
frame.remove();
});
});
});
add_task(async function eventWhenDetachingNestedFrames({ client }) {
const { Page, Runtime } = client;
info("Navigate to a page with nested iframes");
await loadURL(DOC_IFRAME_NESTED);
await Page.enable();
await Runtime.enable();
const { context } = await Runtime.executionContextCreated();
await runFrameDetachedTest(client, 3, async () => {
// Remove top-frame, which also removes any nested frames
await evaluate(client, context.id, async () => {
const frame = document.getElementsByTagName("iframe")[0];
frame.remove();
});
});
});
async function runFrameDetachedTest(client, expectedEventCount, callback) {
const { Page } = client;
const DETACHED = "Page.frameDetached";
const history = new RecordEvents(expectedEventCount);
history.addRecorder({
event: Page.frameDetached,
eventName: DETACHED,
messageFn: payload => {
return `Received ${DETACHED} for frame id ${payload.frameId}`;
},
});
const framesBefore = await getFlattenedFrameTree(client);
await callback();
const framesAfter = await getFlattenedFrameTree(client);
const frameDetachedEvents = await history.record();
if (expectedEventCount == 0) {
is(frameDetachedEvents.length, 0, "Got no frame detached event");
return;
}
// check how many frames were attached or detached
const count = Math.abs(framesBefore.size - framesAfter.size);
is(count, expectedEventCount, "Expected amount of frames detached");
is(
frameDetachedEvents.length,
count,
"Received the expected amount of frameDetached events"
);
// extract the new or removed frames
const framesAll = new Map([...framesBefore, ...framesAfter]);
const expectedFrames = new Map(
[...framesAll].filter(([key, _value]) => {
return framesBefore.has(key) && !framesAfter.has(key);
})
);
frameDetachedEvents.forEach(({ payload }) => {
const { frameId } = payload;
info(`Check frame id ${frameId}`);
const expectedFrame = expectedFrames.get(frameId);
is(
frameId,
expectedFrame.id,
"Got expected frame id for frameDetached event"
);
});
}
|