browser_dbg-breakpoints-popup.js (7407B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */ 4 5 // Verify that we hit breakpoints on popups 6 7 "use strict"; 8 9 const TEST_URI = "https://example.org/document-builder.sjs?html=main page"; 10 const POPUP_URL = `https://example.com/document-builder.sjs?html=${escape(`popup for breakpoints 11 <script> 12 var paused = true; 13 console.log('popup'); 14 paused = false; 15 </script> 16 `)}`; 17 const POPUP_DEBUGGER_STATEMENT_URL = `https://example.com/document-builder.sjs?html=${escape(`popup with debugger; 18 <script> 19 var paused = true; 20 debugger; 21 paused = false; 22 </script> 23 `)}`; 24 25 function isPopupPaused(popupBrowsingContext) { 26 return SpecialPowers.spawn(popupBrowsingContext, [], function () { 27 return content.wrappedJSObject.paused; 28 }); 29 } 30 31 async function openPopup(popupUrl, browser = gBrowser.selectedBrowser) { 32 const onPopupTabSelected = BrowserTestUtils.waitForEvent( 33 gBrowser.tabContainer, 34 "TabSelect" 35 ); 36 const popupBrowsingContext = await SpecialPowers.spawn( 37 browser, 38 [popupUrl], 39 function (url) { 40 const popup = content.open(url); 41 return popup.browsingContext; 42 } 43 ); 44 await onPopupTabSelected; 45 is( 46 gBrowser.selectedBrowser.browsingContext, 47 popupBrowsingContext, 48 "The popup is the selected tab" 49 ); 50 return popupBrowsingContext; 51 } 52 53 async function closePopup(browsingContext) { 54 const onPreviousTabSelected = BrowserTestUtils.waitForEvent( 55 gBrowser.tabContainer, 56 "TabSelect" 57 ); 58 await SpecialPowers.spawn(browsingContext, [], function () { 59 content.close(); 60 }); 61 await onPreviousTabSelected; 62 } 63 64 add_task(async function testPausedByBreakpoint() { 65 await pushPref("devtools.popups.debug", true); 66 67 info("Test breakpoints set in popup scripts"); 68 const dbg = await initDebuggerWithAbsoluteURL(TEST_URI); 69 70 info("Open the popup in order to be able to set a breakpoint"); 71 const firstPopupBrowsingContext = await openPopup(POPUP_URL); 72 73 let source = await waitForSource(dbg, POPUP_URL); 74 75 await selectSource(dbg, source); 76 await addBreakpoint(dbg, source, 4); 77 78 info("Now close and reopen the popup"); 79 let onToolboxSwitchedToTab = dbg.toolbox.once("switched-host-to-tab"); 80 await closePopup(firstPopupBrowsingContext); 81 await onToolboxSwitchedToTab; 82 83 info("Re-open the popup"); 84 onToolboxSwitchedToTab = dbg.toolbox.once("switched-host-to-tab"); 85 const popupBrowsingContext = await openPopup(POPUP_URL); 86 await onToolboxSwitchedToTab; 87 await waitForPaused(dbg); 88 is( 89 await isPopupPaused(popupBrowsingContext), 90 true, 91 "The popup is really paused" 92 ); 93 94 source = await waitForSource(dbg, POPUP_URL); 95 await assertPausedAtSourceAndLine(dbg, source.id, 4); 96 97 await resume(dbg); 98 is( 99 await isPopupPaused(popupBrowsingContext), 100 false, 101 "The popup resumed its execution" 102 ); 103 }); 104 105 add_task(async function testPausedByDebuggerStatement() { 106 info("Test debugger statements in popup scripts"); 107 const dbg = await initDebuggerWithAbsoluteURL(TEST_URI); 108 109 info("Open a popup with a debugger statement"); 110 const popupBrowsingContext = await openPopup(POPUP_DEBUGGER_STATEMENT_URL); 111 await waitForPaused(dbg); 112 is( 113 await isPopupPaused(popupBrowsingContext), 114 true, 115 "The popup is really paused" 116 ); 117 118 const source = findSource(dbg, POPUP_DEBUGGER_STATEMENT_URL); 119 await assertPausedAtSourceAndLine(dbg, source.id, 4); 120 121 await resume(dbg); 122 is( 123 await isPopupPaused(popupBrowsingContext), 124 false, 125 "The popup resumed its execution" 126 ); 127 }); 128 129 add_task(async function testPausedInTwoPopups() { 130 info("Test being paused in two popup at the same time"); 131 const dbg = await initDebuggerWithAbsoluteURL(TEST_URI); 132 133 info("Open the popup in order to be able to set a breakpoint"); 134 const browser = gBrowser.selectedBrowser; 135 const popupBrowsingContext = await openPopup(POPUP_URL); 136 137 const source = await waitForSource(dbg, POPUP_URL); 138 139 await selectSource(dbg, source); 140 await addBreakpoint(dbg, source, 4); 141 142 info("Now close and reopen the popup"); 143 await closePopup(popupBrowsingContext); 144 145 info("Open a first popup which will hit the breakpoint"); 146 const firstPopupBrowsingContext = await openPopup(POPUP_URL); 147 await waitForPaused(dbg); 148 const { targetCommand } = dbg.commands; 149 const firstTarget = targetCommand 150 .getAllTargets([targetCommand.TYPES.FRAME]) 151 .find(targetFront => targetFront.url == POPUP_URL); 152 is( 153 firstTarget.browsingContextID, 154 firstPopupBrowsingContext.id, 155 "The popup target matches the popup BrowsingContext" 156 ); 157 const firstThread = (await firstTarget.getFront("thread")).actorID; 158 is( 159 dbg.selectors.getCurrentThread(), 160 firstThread, 161 "The popup thread is automatically selected on pause" 162 ); 163 is( 164 await isPopupPaused(firstPopupBrowsingContext), 165 true, 166 "The first popup is really paused" 167 ); 168 169 info("Open a second popup which will also hit the breakpoint"); 170 let onAvailable; 171 const onNewTarget = new Promise(resolve => { 172 onAvailable = ({ targetFront }) => { 173 if ( 174 targetFront.url == POPUP_URL && 175 targetFront.browsingContextID != firstPopupBrowsingContext.id 176 ) { 177 targetCommand.unwatchTargets({ 178 types: [targetCommand.TYPES.FRAME], 179 onAvailable, 180 }); 181 resolve(targetFront); 182 } 183 }; 184 }); 185 await targetCommand.watchTargets({ 186 types: [targetCommand.TYPES.FRAME], 187 onAvailable, 188 }); 189 const secondPopupBrowsingContext = await openPopup(POPUP_URL, browser); 190 info("Wait for second popup's target"); 191 const popupTarget = await onNewTarget; 192 is( 193 popupTarget.browsingContextID, 194 secondPopupBrowsingContext.id, 195 "The new target matches the popup WindowGlobal" 196 ); 197 const secondThread = (await popupTarget.getFront("thread")).actorID; 198 await waitForPausedThread(dbg, secondThread); 199 is( 200 dbg.selectors.getCurrentThread(), 201 secondThread, 202 "The second popup thread is automatically selected on pause" 203 ); 204 is( 205 await isPopupPaused(secondPopupBrowsingContext), 206 true, 207 "The second popup is really paused" 208 ); 209 210 info("Resume the execution of the second popup"); 211 await resume(dbg); 212 is( 213 await isPopupPaused(secondPopupBrowsingContext), 214 false, 215 "The second popup resumed its execution" 216 ); 217 is( 218 await isPopupPaused(firstPopupBrowsingContext), 219 true, 220 "The first popup is still paused" 221 ); 222 223 info("Resume the execution of the first popup"); 224 await dbg.actions.selectThread(firstThread); 225 await resume(dbg); 226 is( 227 await isPopupPaused(firstPopupBrowsingContext), 228 false, 229 "The first popup resumed its execution" 230 ); 231 }); 232 233 add_task(async function testClosingOriginalTab() { 234 info( 235 "Test closing the toolbox on the original tab while the popup is kept open" 236 ); 237 const dbg = await initDebuggerWithAbsoluteURL(TEST_URI); 238 await dbg.toolbox.selectTool("webconsole"); 239 240 info("Open a popup"); 241 const originalTab = gBrowser.selectedTab; 242 await openPopup("about:blank"); 243 await wait(1000); 244 const popupTab = gBrowser.selectedTab; 245 gBrowser.selectedTab = originalTab; 246 info("Close the toolbox from the original tab"); 247 await dbg.toolbox.closeToolbox(); 248 await wait(1000); 249 info("Re-select the popup"); 250 gBrowser.selectedTab = popupTab; 251 await wait(1000); 252 });