browser_aboutdebugging_addons_debug_debugger.js (6251B)
1 /* Any copyright is dedicated to the Public Domain. 2 http://creativecommons.org/publicdomain/zero/1.0/ */ 3 "use strict"; 4 5 Services.scriptloader.loadSubScript( 6 "chrome://mochitests/content/browser/devtools/client/debugger/test/mochitest/shared-head.js", 7 this 8 ); 9 10 /* import-globals-from helper-addons.js */ 11 Services.scriptloader.loadSubScript(CHROME_URL_ROOT + "helper-addons.js", this); 12 13 const L10N = new LocalizationHelper( 14 "devtools/client/locales/toolbox.properties" 15 ); 16 17 const EXTENSION_NAME = "temporary-web-extension"; 18 const EXTENSION_ID = "test-devtools@mozilla.org"; 19 20 add_task(async function testOpenDebuggerReload() { 21 await enableExtensionDebugging(); 22 23 info( 24 "The debugger should show the source codes of extension even if " + 25 "devtools.chrome.enabled and devtools.debugger.remote-enabled are off" 26 ); 27 await pushPref("devtools.chrome.enabled", false); 28 await pushPref("devtools.debugger.remote-enabled", false); 29 30 const { document, tab, window } = await openAboutDebugging(); 31 await selectThisFirefoxPage(document, window.AboutDebugging.store); 32 33 await installTemporaryExtensionFromXPI( 34 { 35 background() { 36 window.someRandomMethodName = () => { 37 // This will not be referred from anywhere. 38 // However this is necessary to show as the source code in the debugger. 39 }; 40 }, 41 id: EXTENSION_ID, 42 name: EXTENSION_NAME, 43 }, 44 document 45 ); 46 47 // Select the debugger right away to avoid any noise coming from the inspector. 48 await pushPref("devtools.toolbox.selectedTool", "jsdebugger"); 49 const { devtoolsWindow } = await openAboutDevtoolsToolbox( 50 document, 51 tab, 52 window, 53 EXTENSION_NAME 54 ); 55 const toolbox = getToolbox(devtoolsWindow); 56 const { panelWin } = toolbox.getCurrentPanel(); 57 58 info("Check the state of redux"); 59 ok( 60 panelWin.dbg.store.getState().sourcesTree.isWebExtension, 61 "isWebExtension flag in sourcesTree is true" 62 ); 63 64 const descriptorTitle = devtoolsWindow.document.querySelector( 65 ".qa-descriptor-title" 66 ); 67 is( 68 descriptorTitle.textContent, 69 EXTENSION_NAME, 70 "The add-on name is displayed in the toolbox header" 71 ); 72 73 info("Check whether the element displays correctly"); 74 let sourceList = panelWin.document.querySelector(".sources-list"); 75 ok(sourceList, "Source list element displays correctly"); 76 ok( 77 sourceList.textContent.includes("temporary-web-extension"), 78 "Extension name displays correctly" 79 ); 80 81 const { onResource: onDomCompleteResource } = 82 await toolbox.commands.resourceCommand.waitForNextResource( 83 toolbox.commands.resourceCommand.TYPES.DOCUMENT_EVENT, 84 { 85 ignoreExistingResources: true, 86 predicate: resource => { 87 return ( 88 resource.name === "dom-complete" && 89 resource.targetFront.url.endsWith("background_page.html") 90 ); 91 }, 92 } 93 ); 94 95 info("Reload the addon using a toolbox reload shortcut"); 96 toolbox.win.focus(); 97 synthesizeKeyShortcut(L10N.getStr("toolbox.reload.key"), toolbox.win); 98 99 await onDomCompleteResource; 100 101 info("Wait until a new background log message is logged"); 102 await waitFor(() => { 103 // As React may re-create a new sources-list element, 104 // fetch the latest instance 105 sourceList = panelWin.document.querySelector(".sources-list"); 106 return sourceList?.textContent.includes("temporary-web-extension"); 107 }, "Wait for the source to re-appear"); 108 109 await closeWebExtAboutDevtoolsToolbox(devtoolsWindow, window); 110 await removeTemporaryExtension(EXTENSION_NAME, document); 111 await removeTab(tab); 112 }); 113 114 add_task(async function testAddAndRemoveBreakpoint() { 115 await enableExtensionDebugging(); 116 117 const { document, tab, window } = await openAboutDebugging(); 118 await selectThisFirefoxPage(document, window.AboutDebugging.store); 119 120 await installTemporaryExtensionFromXPI( 121 { 122 background() { 123 window.invokeLogFromWebextension = () => { 124 console.log("From webextension"); 125 }; 126 }, 127 id: EXTENSION_ID, 128 name: EXTENSION_NAME, 129 }, 130 document 131 ); 132 133 // Select the debugger right away to avoid any noise coming from the inspector. 134 await pushPref("devtools.toolbox.selectedTool", "jsdebugger"); 135 const { devtoolsWindow } = await openAboutDevtoolsToolbox( 136 document, 137 tab, 138 window, 139 EXTENSION_NAME 140 ); 141 const toolbox = getToolbox(devtoolsWindow); 142 const dbg = createDebuggerContext(toolbox); 143 144 info("Assert the threads displayed in Source Tree as well as Threads pane"); 145 const sourceTreeThreads = findAllElements(dbg, "sourceTreeThreads"); 146 is( 147 sourceTreeThreads.length, 148 1, 149 "There is only one thread with source in the Source Tree" 150 ); 151 is( 152 sourceTreeThreads[0].textContent, 153 "/_generated_background_page.html", 154 "That thread is the background page" 155 ); 156 157 const threadLabels = findAllElements(dbg, "threadsPaneItems"); 158 is(threadLabels.length, 2, "But there are two threads in the thread panel"); 159 is(threadLabels[0].textContent, "Web Extension Fallback Document"); 160 is(threadLabels[1].textContent, "/_generated_background_page.html"); 161 162 info("Select the source and add a breakpoint"); 163 // Note: the background script filename is dynamically generated id, so we 164 // simply get the first source from the list. 165 const displayedSources = dbg.selectors.getDisplayedSourcesList(); 166 const backgroundScript = displayedSources[0]; 167 await selectSource(dbg, backgroundScript); 168 await addBreakpoint(dbg, backgroundScript, 3); 169 170 info("Trigger the breakpoint and wait for the debugger to pause"); 171 const webconsole = await toolbox.selectTool("webconsole"); 172 const { hud } = webconsole; 173 hud.ui.wrapper.dispatchEvaluateExpression("invokeLogFromWebextension()"); 174 await waitForPaused(dbg); 175 176 info("Resume and remove the breakpoint"); 177 await resume(dbg); 178 await removeBreakpoint(dbg, backgroundScript.id, 3); 179 180 info("Trigger the function again and check the debugger does not pause"); 181 hud.ui.wrapper.dispatchEvaluateExpression("invokeLogFromWebextension()"); 182 await wait(500); 183 assertNotPaused(dbg); 184 185 await closeWebExtAboutDevtoolsToolbox(devtoolsWindow, window); 186 await removeTemporaryExtension(EXTENSION_NAME, document); 187 await removeTab(tab); 188 });