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
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
|
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
// Verify that we hit breakpoints on popups
"use strict";
const TEST_URI = "https://example.org/document-builder.sjs?html=main page";
const POPUP_URL = `https://example.com/document-builder.sjs?html=${escape(`popup for breakpoints
<script>
var paused = true;
console.log('popup');
paused = false;
</script>
`)}`;
const POPUP_DEBUGGER_STATEMENT_URL = `https://example.com/document-builder.sjs?html=${escape(`popup with debugger;
<script>
var paused = true;
debugger;
paused = false;
</script>
`)}`;
function isPopupPaused(popupBrowsingContext) {
return SpecialPowers.spawn(popupBrowsingContext, [], function () {
return content.wrappedJSObject.paused;
});
}
async function openPopup(popupUrl, browser = gBrowser.selectedBrowser) {
const onPopupTabSelected = BrowserTestUtils.waitForEvent(
gBrowser.tabContainer,
"TabSelect"
);
const popupBrowsingContext = await SpecialPowers.spawn(
browser,
[popupUrl],
function (url) {
const popup = content.open(url);
return popup.browsingContext;
}
);
await onPopupTabSelected;
is(
gBrowser.selectedBrowser.browsingContext,
popupBrowsingContext,
"The popup is the selected tab"
);
return popupBrowsingContext;
}
async function closePopup(browsingContext) {
const onPreviousTabSelected = BrowserTestUtils.waitForEvent(
gBrowser.tabContainer,
"TabSelect"
);
await SpecialPowers.spawn(browsingContext, [], function () {
content.close();
});
await onPreviousTabSelected;
}
add_task(async function testPausedByBreakpoint() {
await pushPref("devtools.popups.debug", true);
info("Test breakpoints set in popup scripts");
const dbg = await initDebuggerWithAbsoluteURL(TEST_URI);
info("Open the popup in order to be able to set a breakpoint");
const firstPopupBrowsingContext = await openPopup(POPUP_URL);
let source = await waitForSource(dbg, POPUP_URL);
await selectSource(dbg, source);
await addBreakpoint(dbg, source, 4);
info("Now close and reopen the popup");
await closePopup(firstPopupBrowsingContext);
info("Re-open the popup");
const popupBrowsingContext = await openPopup(POPUP_URL);
await waitForPaused(dbg);
is(
await isPopupPaused(popupBrowsingContext),
true,
"The popup is really paused"
);
source = await waitForSource(dbg, POPUP_URL);
assertPausedAtSourceAndLine(dbg, source.id, 4);
await resume(dbg);
is(
await isPopupPaused(popupBrowsingContext),
false,
"The popup resumed its execution"
);
});
add_task(async function testPausedByDebuggerStatement() {
info("Test debugger statements in popup scripts");
const dbg = await initDebuggerWithAbsoluteURL(TEST_URI);
info("Open a popup with a debugger statement");
const popupBrowsingContext = await openPopup(POPUP_DEBUGGER_STATEMENT_URL);
await waitForPaused(dbg);
is(
await isPopupPaused(popupBrowsingContext),
true,
"The popup is really paused"
);
const source = findSource(dbg, POPUP_DEBUGGER_STATEMENT_URL);
assertPausedAtSourceAndLine(dbg, source.id, 4);
await resume(dbg);
is(
await isPopupPaused(popupBrowsingContext),
false,
"The popup resumed its execution"
);
});
add_task(async function testPausedInTwoPopups() {
info("Test being paused in two popup at the same time");
const dbg = await initDebuggerWithAbsoluteURL(TEST_URI);
info("Open the popup in order to be able to set a breakpoint");
const browser = gBrowser.selectedBrowser;
const popupBrowsingContext = await openPopup(POPUP_URL);
const source = await waitForSource(dbg, POPUP_URL);
await selectSource(dbg, source);
await addBreakpoint(dbg, source, 4);
info("Now close and reopen the popup");
await closePopup(popupBrowsingContext);
info("Open a first popup which will hit the breakpoint");
const firstPopupBrowsingContext = await openPopup(POPUP_URL);
await waitForPaused(dbg);
const { targetCommand } = dbg.commands;
const firstTarget = targetCommand
.getAllTargets([targetCommand.TYPES.FRAME])
.find(targetFront => targetFront.url == POPUP_URL);
is(
firstTarget.browsingContextID,
firstPopupBrowsingContext.id,
"The popup target matches the popup BrowsingContext"
);
const firstThread = (await firstTarget.getFront("thread")).actorID;
is(
dbg.selectors.getCurrentThread(),
firstThread,
"The popup thread is automatically selected on pause"
);
is(
await isPopupPaused(firstPopupBrowsingContext),
true,
"The first popup is really paused"
);
info("Open a second popup which will also hit the breakpoint");
let onAvailable;
const onNewTarget = new Promise(resolve => {
onAvailable = ({ targetFront }) => {
if (
targetFront.url == POPUP_URL &&
targetFront.browsingContextID != firstPopupBrowsingContext.id
) {
targetCommand.unwatchTargets({
types: [targetCommand.TYPES.FRAME],
onAvailable,
});
resolve(targetFront);
}
};
});
await targetCommand.watchTargets({
types: [targetCommand.TYPES.FRAME],
onAvailable,
});
const secondPopupBrowsingContext = await openPopup(POPUP_URL, browser);
info("Wait for second popup's target");
const popupTarget = await onNewTarget;
is(
popupTarget.browsingContextID,
secondPopupBrowsingContext.id,
"The new target matches the popup WindowGlobal"
);
const secondThread = (await popupTarget.getFront("thread")).actorID;
await waitForPausedThread(dbg, secondThread);
is(
dbg.selectors.getCurrentThread(),
secondThread,
"The second popup thread is automatically selected on pause"
);
is(
await isPopupPaused(secondPopupBrowsingContext),
true,
"The second popup is really paused"
);
info("Resume the execution of the second popup");
await resume(dbg);
is(
await isPopupPaused(secondPopupBrowsingContext),
false,
"The second popup resumed its execution"
);
is(
await isPopupPaused(firstPopupBrowsingContext),
true,
"The first popup is still paused"
);
info("Resume the execution of the first popup");
await dbg.actions.selectThread(firstThread);
await resume(dbg);
is(
await isPopupPaused(firstPopupBrowsingContext),
false,
"The first popup resumed its execution"
);
});
add_task(async function testClosingOriginalTab() {
info(
"Test closing the toolbox on the original tab while the popup is kept open"
);
const dbg = await initDebuggerWithAbsoluteURL(TEST_URI);
await dbg.toolbox.selectTool("webconsole");
info("Open a popup");
const originalTab = gBrowser.selectedTab;
await openPopup("about:blank");
await wait(1000);
const popupTab = gBrowser.selectedTab;
gBrowser.selectedTab = originalTab;
info("Close the toolbox from the original tab");
await dbg.toolbox.closeToolbox();
await wait(1000);
info("Re-select the popup");
gBrowser.selectedTab = popupTab;
await wait(1000);
});
|