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
|
/* 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>
`);
add_task(async function pageWithoutFrames({ client }) {
const { Page } = client;
info("Navigate to a page without a frame");
await loadURL(DOC);
const { frameTree } = await Page.getFrameTree();
ok(!!frameTree.frame, "Expected frame details found");
const expectedFrames = await getFlattenedFrameList();
// Check top-level frame
const expectedFrame = expectedFrames.get(frameTree.frame.id);
is(frameTree.frame.id, expectedFrame.id, "Expected frame id found");
is(frameTree.frame.parentId, undefined, "Parent frame doesn't exist");
is(frameTree.name, undefined, "Top frame doens't contain name property");
is(frameTree.frame.url, expectedFrame.url, "Expected url found");
is(frameTree.childFrames, undefined, "No sub frames found");
});
add_task(async function PageWithFrames({ client }) {
const { Page } = client;
info("Navigate to a page with frames");
await loadURL(DOC_IFRAME_MULTI);
const { frameTree } = await Page.getFrameTree();
ok(!!frameTree.frame, "Expected frame details found");
const expectedFrames = await getFlattenedFrameList();
let frame = frameTree.frame;
let expectedFrame = expectedFrames.get(frame.id);
info(`Check top frame with id: ${frame.id}`);
is(frame.id, expectedFrame.id, "Expected frame id found");
is(frame.parentId, undefined, "Parent frame doesn't exist");
is(frame.name, undefined, "Top frame doesn't contain name property");
is(frame.url, expectedFrame.url, "Expected URL found");
is(frameTree.childFrames.length, 2, "Expected two sub frames");
for (const childFrameTree of frameTree.childFrames) {
let frame = childFrameTree.frame;
let expectedFrame = expectedFrames.get(frame.id);
info(`Check sub frame with id: ${frame.id}`);
is(frame.id, expectedFrame.id, "Expected frame id found");
is(frame.parentId, expectedFrame.parentId, "Expected parent id found");
is(frame.name, expectedFrame.name, "Frame has expected name set");
is(frame.url, expectedFrame.url, "Expected URL found");
is(childFrameTree.childFrames, undefined, "No sub frames found");
}
});
add_task(async function pageWithNestedFrames({ client }) {
const { Page } = client;
info("Navigate to a page with nested frames");
await loadURL(DOC_IFRAME_NESTED);
const { frameTree } = await Page.getFrameTree();
ok(!!frameTree.frame, "Expected frame details found");
const expectedFrames = await getFlattenedFrameList();
let frame = frameTree.frame;
let expectedFrame = expectedFrames.get(frame.id);
info(`Check top frame with id: ${frame.id}`);
is(frame.id, expectedFrame.id, "Expected frame id found");
is(frame.parentId, undefined, "Parent frame doesn't exist");
is(frame.name, undefined, "Top frame doesn't contain name property");
is(frame.url, expectedFrame.url, "Expected URL found");
is(frameTree.childFrames.length, 1, "Expected a single sub frame");
const childFrameTree = frameTree.childFrames[0];
frame = childFrameTree.frame;
expectedFrame = expectedFrames.get(frame.id);
info(`Check sub frame with id: ${frame.id}`);
is(frame.id, expectedFrame.id, "Expected frame id found");
is(frame.parentId, expectedFrame.parentId, "Expected parent id found");
is(frame.name, expectedFrame.name, "Frame has expected name set");
is(frame.url, expectedFrame.url, "Expected URL found");
is(childFrameTree.childFrames.length, 2, "Expected two sub frames");
let nestedChildFrameTree = childFrameTree.childFrames[0];
frame = nestedChildFrameTree.frame;
expectedFrame = expectedFrames.get(frame.id);
info(`Check first nested frame with id: ${frame.id}`);
is(frame.id, expectedFrame.id, "Expected frame id found");
is(frame.parentId, expectedFrame.parentId, "Expected parent id found");
is(frame.name, expectedFrame.name, "Frame has expected name set");
is(frame.url, expectedFrame.url, "Expected URL found");
is(nestedChildFrameTree.childFrames, undefined, "No sub frames found");
nestedChildFrameTree = childFrameTree.childFrames[1];
frame = nestedChildFrameTree.frame;
expectedFrame = expectedFrames.get(frame.id);
info(`Check second nested frame with id: ${frame.id}`);
is(frame.id, expectedFrame.id, "Expected frame id found");
is(frame.parentId, expectedFrame.parentId, "Expected parent id found");
is(frame.name, expectedFrame.name, "Frame has expected name set");
is(frame.url, expectedFrame.url, "Expected URL found");
is(nestedChildFrameTree.childFrames, undefined, "No sub frames found");
});
/**
* Retrieve all frames for the current tab as flattened list.
*/
function getFlattenedFrameList() {
return SpecialPowers.spawn(gBrowser.selectedBrowser, [], () => {
const frames = new Map();
function getFrameDetails(context) {
const frameElement = context.embedderElement;
const frame = {
id: context.id.toString(),
parentId: context.parent ? context.parent.id.toString() : null,
loaderId: null,
name: frameElement?.id || frameElement?.name,
url: context.docShell.domWindow.location.href,
securityOrigin: null,
mimeType: null,
};
if (context.parent) {
frame.parentId = context.parent.id.toString();
}
frames.set(context.id.toString(), frame);
for (const childContext of context.children) {
getFrameDetails(childContext);
}
}
getFrameDetails(content.docShell.browsingContext);
return frames;
});
}
|