Bug 1780912 - [devtools] Open toolboxes for local WebExtension in dedicated window. r=jdescottes

This should hopefully help debug addons displaying panels/popups.

Differential Revision: https://phabricator.services.mozilla.com/D155393
This commit is contained in:
Alexandre Poirot 2022-09-07 21:00:17 +00:00
Родитель e3d1d71728
Коммит 8792e1fba5
12 изменённых файлов: 108 добавлений и 53 удалений

Просмотреть файл

@ -26,7 +26,10 @@ const {
getCurrentRuntime, getCurrentRuntime,
} = require("devtools/client/aboutdebugging/src/modules/runtimes-state-helper"); } = require("devtools/client/aboutdebugging/src/modules/runtimes-state-helper");
const { gDevTools } = require("devtools/client/framework/devtools");
const { const {
DEBUG_TARGETS,
DEBUG_TARGET_PANE, DEBUG_TARGET_PANE,
REQUEST_EXTENSIONS_FAILURE, REQUEST_EXTENSIONS_FAILURE,
REQUEST_EXTENSIONS_START, REQUEST_EXTENSIONS_START,
@ -73,29 +76,39 @@ function inspectDebugTarget(type, id) {
return async ({ dispatch, getState }) => { return async ({ dispatch, getState }) => {
const runtime = getCurrentRuntime(getState().runtimes); const runtime = getCurrentRuntime(getState().runtimes);
const urlParams = { if (
id, type == DEBUG_TARGETS.EXTENSION &&
type, runtime.id === RUNTIMES.THIS_FIREFOX
}; ) {
// Bug 1780912: To avoid UX issues when debugging local web extensions,
if (runtime.id !== RUNTIMES.THIS_FIREFOX) { // we are opening the toolbox in an independant window.
urlParams.remoteId = remoteClientManager.getRemoteId( // Whereas all others are opened in new tabs.
runtime.id, gDevTools.showToolboxForWebExtension(id);
runtime.type
);
}
const url = `about:devtools-toolbox?${new window.URLSearchParams(
urlParams
)}`;
const existingTab = getTabForUrl(url);
if (existingTab) {
const navigator = existingTab.ownerGlobal;
navigator.gBrowser.selectedTab = existingTab;
navigator.focus();
} else { } else {
window.open(url); const urlParams = {
id,
type,
};
if (runtime.id !== RUNTIMES.THIS_FIREFOX) {
urlParams.remoteId = remoteClientManager.getRemoteId(
runtime.id,
runtime.type
);
}
const url = `about:devtools-toolbox?${new window.URLSearchParams(
urlParams
)}`;
const existingTab = getTabForUrl(url);
if (existingTab) {
const navigator = existingTab.ownerGlobal;
navigator.gBrowser.selectedTab = existingTab;
navigator.focus();
} else {
window.open(url);
}
} }
dispatch( dispatch(

Просмотреть файл

@ -75,6 +75,7 @@ class DebugTargetItem extends PureComponent {
return dom.li( return dom.li(
{ {
className: "card debug-target-item qa-debug-target-item", className: "card debug-target-item qa-debug-target-item",
"data-qa-target-type": this.props.target.type,
}, },
this.renderIcon(), this.renderIcon(),
this.renderName(), this.renderName(),

Просмотреть файл

@ -134,7 +134,7 @@ add_task(async function testWebExtensionsToolboxWebConsole() {
document document
); );
const { devtoolsTab, devtoolsWindow } = await openAboutDevtoolsToolbox( const { devtoolsWindow } = await openAboutDevtoolsToolbox(
document, document,
tab, tab,
window, window,
@ -250,7 +250,7 @@ add_task(async function testWebExtensionsToolboxWebConsole() {
// And we received the evaluation result // And we received the evaluation result
await onEvaluationResultAfterReload; await onEvaluationResultAfterReload;
await closeAboutDevtoolsToolbox(document, devtoolsTab, window); await closeWebExtAboutDevtoolsToolbox(devtoolsWindow, window);
// Note that it seems to be important to remove the addons in the reverse order // Note that it seems to be important to remove the addons in the reverse order
// from which they were installed... // from which they were installed...
@ -301,7 +301,7 @@ add_task(async function testWebExtensionNoBgScript() {
document document
); );
const { devtoolsTab, devtoolsWindow } = await openAboutDevtoolsToolbox( const { devtoolsWindow } = await openAboutDevtoolsToolbox(
document, document,
tab, tab,
window, window,
@ -340,7 +340,7 @@ add_task(async function testWebExtensionNoBgScript() {
"We get the addon's popup CSS error message" "We get the addon's popup CSS error message"
); );
await closeAboutDevtoolsToolbox(document, devtoolsTab, window); await closeWebExtAboutDevtoolsToolbox(devtoolsWindow, window);
await removeTemporaryExtension(POPUPONLY_ADDON_NAME, document); await removeTemporaryExtension(POPUPONLY_ADDON_NAME, document);
await removeTab(tab); await removeTab(tab);
}); });
@ -383,7 +383,7 @@ add_task(async function testWebExtensionTwoReloads() {
// instead. // instead.
const addonTarget = findDebugTargetByText(BACKGROUND_ADDON_NAME, document); const addonTarget = findDebugTargetByText(BACKGROUND_ADDON_NAME, document);
const { devtoolsTab, devtoolsWindow } = await openAboutDevtoolsToolbox( const { devtoolsWindow } = await openAboutDevtoolsToolbox(
document, document,
tab, tab,
window, window,
@ -431,7 +431,7 @@ add_task(async function testWebExtensionTwoReloads() {
hud.ui.wrapper.dispatchEvaluateExpression("40+2"); hud.ui.wrapper.dispatchEvaluateExpression("40+2");
await waitUntil(() => findMessageByType(hud, "42", ".result")); await waitUntil(() => findMessageByType(hud, "42", ".result"));
await closeAboutDevtoolsToolbox(document, devtoolsTab, window); await closeWebExtAboutDevtoolsToolbox(devtoolsWindow, window);
await removeTemporaryExtension(BACKGROUND_ADDON_NAME, document); await removeTemporaryExtension(BACKGROUND_ADDON_NAME, document);
await removeTab(tab); await removeTab(tab);
}); });

Просмотреть файл

@ -35,7 +35,7 @@ add_task(async () => {
document document
); );
const { devtoolsTab, devtoolsWindow } = await openAboutDevtoolsToolbox( const { devtoolsWindow } = await openAboutDevtoolsToolbox(
document, document,
tab, tab,
window, window,
@ -59,7 +59,7 @@ add_task(async () => {
"Extension name displays correctly" "Extension name displays correctly"
); );
await closeAboutDevtoolsToolbox(document, devtoolsTab, window); await closeWebExtAboutDevtoolsToolbox(devtoolsWindow, window);
await removeTemporaryExtension(EXTENSION_NAME, document); await removeTemporaryExtension(EXTENSION_NAME, document);
await removeTab(tab); await removeTab(tab);
}); });

Просмотреть файл

@ -40,7 +40,7 @@ add_task(async function testWebExtensionsToolboxWebConsole() {
); );
info("Open a toolbox to debug the addon"); info("Open a toolbox to debug the addon");
const { devtoolsTab, devtoolsWindow } = await openAboutDevtoolsToolbox( const { devtoolsWindow } = await openAboutDevtoolsToolbox(
document, document,
tab, tab,
window, window,
@ -80,7 +80,7 @@ add_task(async function testWebExtensionsToolboxWebConsole() {
"The dark color scheme simulation button exists and is hidden" "The dark color scheme simulation button exists and is hidden"
); );
await closeAboutDevtoolsToolbox(document, devtoolsTab, window); await closeWebExtAboutDevtoolsToolbox(devtoolsWindow, window);
await removeTemporaryExtension(ADDON_NAME, document); await removeTemporaryExtension(ADDON_NAME, document);
await removeTab(tab); await removeTab(tab);
}); });

Просмотреть файл

@ -37,7 +37,7 @@ add_task(async function testWebExtensionsToolboxNoBackgroundPage() {
); );
info("Open a toolbox to debug the addon"); info("Open a toolbox to debug the addon");
const { devtoolsTab, devtoolsWindow } = await openAboutDevtoolsToolbox( const { devtoolsWindow } = await openAboutDevtoolsToolbox(
document, document,
tab, tab,
window, window,
@ -70,7 +70,7 @@ add_task(async function testWebExtensionsToolboxNoBackgroundPage() {
"nodeActor has the expected inlineTextChild value" "nodeActor has the expected inlineTextChild value"
); );
await closeAboutDevtoolsToolbox(document, devtoolsTab, window); await closeWebExtAboutDevtoolsToolbox(devtoolsWindow, window);
await removeTemporaryExtension(ADDON_NOBG_NAME, document); await removeTemporaryExtension(ADDON_NOBG_NAME, document);
await removeTab(tab); await removeTab(tab);
}); });

Просмотреть файл

@ -57,12 +57,13 @@ add_task(async function testWebExtensionsToolboxWebConsole() {
); );
info("Open a toolbox to debug the addon"); info("Open a toolbox to debug the addon");
const { devtoolsTab, devtoolsWindow } = await openAboutDevtoolsToolbox( const { devtoolsWindow } = await openAboutDevtoolsToolbox(
document, document,
tab, tab,
aboutDebuggingWindow, aboutDebuggingWindow,
ADDON_NAME ADDON_NAME
); );
const toolbox = getToolbox(devtoolsWindow); const toolbox = getToolbox(devtoolsWindow);
const webconsole = await toolbox.selectTool("webconsole"); const webconsole = await toolbox.selectTool("webconsole");
@ -117,7 +118,7 @@ add_task(async function testWebExtensionsToolboxWebConsole() {
"Got the expected manifest from WebExtension API" "Got the expected manifest from WebExtension API"
); );
await closeAboutDevtoolsToolbox(document, devtoolsTab, aboutDebuggingWindow); await closeWebExtAboutDevtoolsToolbox(devtoolsWindow, aboutDebuggingWindow);
is( is(
Services.prefs.getBoolPref("ui.popup.disable_autohide"), Services.prefs.getBoolPref("ui.popup.disable_autohide"),
@ -230,7 +231,6 @@ async function waitForExtension(addonName) {
*/ */
function disablePopupAutohide(toolbox) { function disablePopupAutohide(toolbox) {
return new Promise(resolve => { return new Promise(resolve => {
toolbox.doc.getElementById("toolbox-meatball-menu-button").click();
toolbox.doc.addEventListener( toolbox.doc.addEventListener(
"popupshown", "popupshown",
() => { () => {
@ -242,5 +242,6 @@ function disablePopupAutohide(toolbox) {
}, },
{ once: true } { once: true }
); );
toolbox.doc.getElementById("toolbox-meatball-menu-button").click();
}); });
} }

Просмотреть файл

@ -40,11 +40,12 @@ add_task(async function testWebExtensionToolboxReload() {
document document
); );
const { const { devtoolsDocument, devtoolsWindow } = await openAboutDevtoolsToolbox(
devtoolsDocument, document,
devtoolsTab, tab,
devtoolsWindow, window,
} = await openAboutDevtoolsToolbox(document, tab, window, ADDON_NAME); ADDON_NAME
);
const toolbox = getToolbox(devtoolsWindow); const toolbox = getToolbox(devtoolsWindow);
ok( ok(
@ -123,7 +124,7 @@ add_task(async function testWebExtensionToolboxReload() {
await waitForLoadedPanelsReload(); await waitForLoadedPanelsReload();
await closeAboutDevtoolsToolbox(document, devtoolsTab, window); await closeWebExtAboutDevtoolsToolbox(devtoolsWindow, window);
await removeTemporaryExtension(ADDON_NAME, document); await removeTemporaryExtension(ADDON_NAME, document);
await removeTab(tab); await removeTab(tab);
}); });

Просмотреть файл

@ -40,7 +40,7 @@ add_task(async () => {
document document
); );
const { devtoolsTab, devtoolsWindow } = await openAboutDevtoolsToolbox( const { devtoolsWindow } = await openAboutDevtoolsToolbox(
document, document,
tab, tab,
window, window,
@ -84,7 +84,7 @@ add_task(async () => {
is(user2.name, "Bob", "user 2 has the expected name"); is(user2.name, "Bob", "user 2 has the expected name");
is(user2.age, 24, "user 2 has the expected age"); is(user2.age, 24, "user 2 has the expected age");
await closeAboutDevtoolsToolbox(document, devtoolsTab, window); await closeWebExtAboutDevtoolsToolbox(devtoolsWindow, window);
await removeTemporaryExtension(EXTENSION_NAME, document); await removeTemporaryExtension(EXTENSION_NAME, document);
await removeTab(tab); await removeTab(tab);
}); });

Просмотреть файл

@ -86,7 +86,7 @@ add_task(
}); });
info("Open a DevTools toolbox on the target extension"); info("Open a DevTools toolbox on the target extension");
const { devtoolsTab, devtoolsWindow } = await openAboutDevtoolsToolbox( const { devtoolsWindow } = await openAboutDevtoolsToolbox(
document, document,
tab, tab,
window, window,
@ -183,7 +183,7 @@ add_task(
"Verify event page is terminated on idle after closing the DevTools toolbox" "Verify event page is terminated on idle after closing the DevTools toolbox"
); );
await closeAboutDevtoolsToolbox(document, devtoolsTab, window); await closeWebExtAboutDevtoolsToolbox(devtoolsWindow, window);
await triggerExtensionEventPageIdleTimeout(EXTENSION_ID); await triggerExtensionEventPageIdleTimeout(EXTENSION_ID);
await waitForBGStatusUpdate; await waitForBGStatusUpdate;
await assertBackgroundStatus(EXTENSION_NAME, { await assertBackgroundStatus(EXTENSION_NAME, {

Просмотреть файл

@ -54,7 +54,7 @@ add_task(async function testNodePickerInExtensionPopup() {
document document
); );
const { devtoolsTab, devtoolsWindow } = await openAboutDevtoolsToolbox( const { devtoolsWindow } = await openAboutDevtoolsToolbox(
document, document,
tab, tab,
window, window,
@ -93,7 +93,7 @@ add_task(async function testNodePickerInExtensionPopup() {
const nodeFront = await onNewNodeFront; const nodeFront = await onNewNodeFront;
is(nodeFront.id, "pick-me", "The expected node front was selected"); is(nodeFront.id, "pick-me", "The expected node front was selected");
await closeAboutDevtoolsToolbox(document, devtoolsTab, window); await closeWebExtAboutDevtoolsToolbox(devtoolsWindow, window);
await removeTemporaryExtension(ADDON_NAME, document); await removeTemporaryExtension(ADDON_NAME, document);
await removeTab(tab); await removeTab(tab);
}); });

Просмотреть файл

@ -85,17 +85,34 @@ async function openAboutDevtoolsToolbox(
info("Open about:devtools-toolbox page"); info("Open about:devtools-toolbox page");
const target = findDebugTargetByText(targetText, doc); const target = findDebugTargetByText(targetText, doc);
ok(target, `${targetText} tab target appeared`); ok(target, `${targetText} tab target appeared`);
const {
DEBUG_TARGETS,
} = require("devtools/client/aboutdebugging/src/constants");
const isWebExtension = target.dataset.qaTargetType == DEBUG_TARGETS.EXTENSION;
const inspectButton = target.querySelector(".qa-debug-target-inspect-button"); const inspectButton = target.querySelector(".qa-debug-target-inspect-button");
ok(inspectButton, `Inspect button for ${targetText} appeared`); ok(inspectButton, `Inspect button for ${targetText} appeared`);
inspectButton.click(); inspectButton.click();
const onToolboxReady = gDevTools.once("toolbox-ready");
await Promise.all([ await Promise.all([
waitUntil(() => tab.nextElementSibling),
waitForAboutDebuggingRequests(win.AboutDebugging.store), waitForAboutDebuggingRequests(win.AboutDebugging.store),
shouldWaitToolboxReady shouldWaitToolboxReady ? onToolboxReady : Promise.resolve(),
? gDevTools.once("toolbox-ready")
: Promise.resolve(),
]); ]);
// WebExtension open a toolbox in a dedicated window
if (isWebExtension) {
const toolbox = await onToolboxReady;
return {
devtoolsBrowser: null,
devtoolsDocument: toolbox.doc,
devtoolsTab: null,
devtoolsWindow: toolbox.win,
};
}
await waitUntil(() => tab.nextElementSibling);
info("Wait for about:devtools-toolbox tab will be selected"); info("Wait for about:devtools-toolbox tab will be selected");
const devtoolsTab = tab.nextElementSibling; const devtoolsTab = tab.nextElementSibling;
await waitUntil(() => gBrowser.selectedTab === devtoolsTab); await waitUntil(() => gBrowser.selectedTab === devtoolsTab);
@ -155,6 +172,17 @@ async function closeAboutDevtoolsToolbox(
await waitForAboutDebuggingRequests(win.AboutDebugging.store); await waitForAboutDebuggingRequests(win.AboutDebugging.store);
} }
async function closeWebExtAboutDevtoolsToolbox(devtoolsWindow, win) {
// Wait for all requests to settle on the opened about:devtools toolbox.
const toolbox = getToolbox(devtoolsWindow);
await toolbox.commands.client.waitForRequestsToSettle();
info("Close the toolbox and wait for its destruction");
await toolbox.destroy();
await waitForAboutDebuggingRequests(win.AboutDebugging.store);
}
async function reloadAboutDebugging(tab) { async function reloadAboutDebugging(tab) {
info("reload about:debugging"); info("reload about:debugging");
@ -443,6 +471,12 @@ async function synthesizeUrlKeyInput(toolbox, inputEl, url) {
* The ID of the add-on to click on. * The ID of the add-on to click on.
*/ */
function clickOnAddonWidget(addonId) { function clickOnAddonWidget(addonId) {
// Devtools are in another window and may have the focus.
// Ensure focusing the browser window when clicking on the widget.
const focusedWin = Services.focus.focusedWindow;
if (focusedWin != window) {
window.focus();
}
// Find the browserAction button that will show the webextension popup. // Find the browserAction button that will show the webextension popup.
const widgetId = addonId.toLowerCase().replace(/[^a-z0-9_-]/g, "_"); const widgetId = addonId.toLowerCase().replace(/[^a-z0-9_-]/g, "_");
const browserActionId = widgetId + "-browser-action"; const browserActionId = widgetId + "-browser-action";
@ -451,4 +485,9 @@ function clickOnAddonWidget(addonId) {
info("Show the web extension popup"); info("Show the web extension popup");
browserActionEl.click(); browserActionEl.click();
// And restore the focus right after having clicked.
if (focusedWin != window) {
focusedWin.focus();
}
} }