commit 725e64c6c936486a471e3e5f32134a0e6b8df13a parent 5dd83104b28eb38d47eab54991e5afe4f2c2117b Author: Tooru Fujisawa <arai_a@mac.com> Date: Fri, 17 Oct 2025 02:45:00 +0000 Bug 1993731 - Do not show the Ask an AI Chatbot menu item asynchronously. r=Mardak,firefox-ai-ml-reviewers,sclements Differential Revision: https://phabricator.services.mozilla.com/D268488 Diffstat:
10 files changed, 62 insertions(+), 15 deletions(-)
diff --git a/browser/base/content/nsContextMenu.sys.mjs b/browser/base/content/nsContextMenu.sys.mjs @@ -1381,7 +1381,7 @@ export class nsContextMenu { count = 0; } else if (!menuItem.hidden) { - if (menuItem.localName == "menu") { + if (menuItem.localName == "menu" && menuItem.menupopup) { this.showHideSeparators(menuItem.menupopup); } else if (menuItem.localName == "menugroup") { this.showHideSeparators(menuItem); diff --git a/browser/base/content/test/contextMenu/browser_contextmenu.js b/browser/base/content/test/contextMenu/browser_contextmenu.js @@ -190,6 +190,9 @@ add_task(async function test_plaintext() { true, "---", null, + ...askChatMenu, + "---", + null, "context-viewsource", true, ]); @@ -376,6 +379,8 @@ add_task(async function test_linkpreviewcommand_not_on_text() { "---", null, ...askChatMenu, + "---", + null, "context-viewsource", true, ], @@ -1610,6 +1615,8 @@ add_task(async function test_dom_full_screen() { "---", null, ...askChatMenu, + "---", + null, "context-viewsource", true, ]); @@ -1705,6 +1712,8 @@ add_task(async function test_pagemenu2() { "---", null, ...askChatMenu, + "---", + null, "context-viewsource", true, ], @@ -2376,6 +2385,8 @@ add_task(async function test_background_image() { "---", null, ...askChatMenu, + "---", + null, "context-viewsource", true, ]; diff --git a/browser/base/content/test/contextMenu/browser_contextmenu_add_search_engine.js b/browser/base/content/test/contextMenu/browser_contextmenu_add_search_engine.js @@ -56,6 +56,8 @@ add_task(async function test_text_input_spellcheck_noform() { "---", null, ...askChatMenu, + "---", + null, "spell-check-enabled", true, "spell-dictionaries", @@ -119,6 +121,8 @@ add_task(async function test_text_input_spellcheck_loginform() { "---", null, ...askChatMenu, + "---", + null, "spell-check-enabled", true, "spell-dictionaries", @@ -250,6 +254,8 @@ add_task(async function test_searchform_non_http() { "---", null, ...askChatMenu, + "---", + null, "spell-check-enabled", true, "spell-dictionaries", diff --git a/browser/base/content/test/contextMenu/browser_contextmenu_contenteditable.js b/browser/base/content/test/contextMenu/browser_contextmenu_contenteditable.js @@ -23,6 +23,8 @@ const askChatMenu = [ // Need a blank entry here because the Ask Chat submenu is dynamically built with no ids. "", null, + "---", + null, ]; async function openMenuAndPaste(browser, useFormatting) { diff --git a/browser/base/content/test/contextMenu/browser_contextmenu_input.js b/browser/base/content/test/contextMenu/browser_contextmenu_input.js @@ -79,6 +79,8 @@ add_task(async function test_text_input() { "---", null, ...askChatMenu, + "---", + null, "spell-check-enabled", true, ], @@ -113,6 +115,8 @@ add_task(async function test_text_input_disabled() { "---", null, ...askChatMenu, + "---", + null, "spell-check-enabled", true, ], @@ -232,6 +236,8 @@ add_task(async function firefox_relay_input() { "---", null, ...askChatMenu, + "---", + null, "spell-check-enabled", true, ], @@ -351,6 +357,8 @@ add_task( "---", null, ...askChatMenu, + "---", + null, "context-viewsource", true, ], @@ -393,6 +401,8 @@ add_task(async function test_search_input() { "---", null, ...askChatMenu, + "---", + null, "spell-check-enabled", true, ], diff --git a/browser/base/content/test/contextMenu/browser_contextmenu_spellcheck.js b/browser/base/content/test/contextMenu/browser_contextmenu_spellcheck.js @@ -56,6 +56,8 @@ add_task(async function test_text_input_spellcheck() { "---", null, ...askChatMenu, + "---", + null, "spell-check-enabled", true, "spell-dictionaries", @@ -120,6 +122,8 @@ add_task(async function test_text_input_spellcheckwrong() { "---", null, ...askChatMenu, + "---", + null, "spell-check-enabled", true, "spell-dictionaries", @@ -163,6 +167,8 @@ const kCorrectItems = [ "---", null, ...askChatMenu, + "---", + null, "spell-check-enabled", true, "spell-dictionaries", diff --git a/browser/base/content/test/contextMenu/contextmenu_common.js b/browser/base/content/test/contextMenu/contextmenu_common.js @@ -421,7 +421,7 @@ async function test_contextmenu(selector, menuItems, options = {}) { menuItems.includes("context-viewpartialsource-selection"); const askChatIndex = menuItems.indexOf("context-ask-chat"); - const isAskChatLastItem = menuItems.at(-4) === "context-ask-chat"; + const isAskChatLastItem = menuItems.at(-6) === "context-ask-chat"; if (askChatIndex >= 2) { hasSeparatorAboveAskChat = menuItems[askChatIndex - 2] === "---"; } diff --git a/browser/base/content/test/general/browser_bug417483.js b/browser/base/content/test/general/browser_bug417483.js @@ -1,4 +1,9 @@ add_task(async function () { + // The frame-sep element is shared with "Ask an AI Chatbot". + await SpecialPowers.pushPrefEnv({ + set: [["browser.ml.chat.menu", false]], + }); + let loadedPromise = BrowserTestUtils.browserLoaded( gBrowser.selectedBrowser, true diff --git a/browser/components/genai/GenAI.sys.mjs b/browser/components/genai/GenAI.sys.mjs @@ -670,11 +670,10 @@ export const GenAI = { contextTabs = null, } = contextMenu; - showItem(menu, false); - // DO NOT show menu when inside an extension panel const uri = browser.browsingContext.currentURI.spec; if (uri.startsWith("moz-extension:")) { + showItem(menu, false); return; } @@ -698,6 +697,7 @@ export const GenAI = { break; } if (!canShow) { + showItem(menu, false); return; } @@ -719,6 +719,9 @@ export const GenAI = { menu.menupopup?.remove(); } + // NOTE: Show the menu item synchronously, before any `await`. + showItem(menu, true); + // Determine if we have selection or should use page content const context = { contentType: "selection", @@ -806,8 +809,6 @@ export const GenAI = { Services.prefs.setBoolPref("browser.ml.chat.menu", false); } }); - - showItem(menu, true); }, /** diff --git a/browser/components/sidebar/tests/browser/browser_sidebar_context_menu.js b/browser/components/sidebar/tests/browser/browser_sidebar_context_menu.js @@ -330,17 +330,23 @@ add_task(async function test_tool_context_menu() { contextMenu.querySelector("menuseparator").hidden, "menuseparator is hidden" ); - - const toolMenuItems = [ - ...contextMenu.querySelectorAll("[customized-tool='true']"), - ]; - Assert.equal( - !!toolMenuItems.length && toolMenuItems.every(item => !item.hidden), - true, - "Tool menuitems are visible" - ); }); + // The submenu is populated asynchronously. + await BrowserTestUtils.waitForMutationCondition( + contextMenu, + { childList: true, subtree: true, attributes: true }, + () => { + const toolMenuItems = [ + ...contextMenu.querySelectorAll("[customized-tool='true']"), + ]; + return ( + !!toolMenuItems.length && toolMenuItems.every(item => !item.hidden) + ); + } + ); + Assert.ok(true, "Tool menuitems are visible"); + contextMenu.hidePopup(); await openAndWaitForContextMenu(contextMenu, sidebarMain, () => {