commit eddf4c14825c22ce93798d9d5bad09842c0aa56e
parent d15bf493910aca41ba73ee1e79813e59a0bd9573
Author: Edgar Chen <echen@mozilla.com>
Date: Thu, 11 Dec 2025 12:12:32 +0000
Bug 2005081 - Ensure clipboard paste button is dismissed after navigation; r=Gijs,tschuster
Differential Revision: https://phabricator.services.mozilla.com/D275694
Diffstat:
4 files changed, 64 insertions(+), 1 deletion(-)
diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js
@@ -2250,7 +2250,7 @@ var XULBrowserWindow = {
// Ensure we close any remaining open locationspecific panels
if (!isSameDocument) {
- closeOpenPanels("panel[locationspecific='true']");
+ closeOpenPanels(":is(panel, menupopup)[locationspecific='true']");
}
gPermissionPanel.onLocationChange();
diff --git a/dom/events/test/clipboard/browser.toml b/dom/events/test/clipboard/browser.toml
@@ -17,6 +17,12 @@ run-if = [
"os != 'win'", # The popupmenus dismiss when access keys for disabled items are pressed on windows
]
+["browser_navigator_clipboard_contextmenu_dismiss.js"]
+support-files = [
+ "file_toplevel.html",
+ "file_iframe.html",
+]
+
["browser_navigator_clipboard_contextmenu_suppression.js"]
support-files = [
"file_toplevel.html",
diff --git a/dom/events/test/clipboard/browser_navigator_clipboard_contextmenu_dismiss.js b/dom/events/test/clipboard/browser_navigator_clipboard_contextmenu_dismiss.js
@@ -0,0 +1,56 @@
+/* -*- Mode: JavaScript; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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/. */
+
+"use strict";
+
+const kContentFileUrl = kBaseUrlForContent + "file_toplevel.html";
+
+async function readText(aBrowser) {
+ return SpecialPowers.spawn(aBrowser, [], () => {
+ content.document.notifyUserGestureActivation();
+ content.eval(`navigator.clipboard.readText();`);
+ });
+}
+
+add_task(async function test_context_menu_dimiss_tab_navigate() {
+ await BrowserTestUtils.withNewTab(kContentFileUrl, async aBrowser => {
+ info(`Randomized text to avoid overlappings with other tests`);
+ await promiseWritingRandomTextToClipboard();
+
+ info(`Wait for paste context menu is shown`);
+ let pasteButtonIsShown = promisePasteButtonIsShown();
+ await readText(aBrowser);
+ await pasteButtonIsShown;
+
+ info("Navigate tab");
+ let pasteButtonIsHidden = promisePasteButtonIsHidden();
+ aBrowser.loadURI(Services.io.newURI("https://example.com/"), {
+ triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal(),
+ });
+
+ info(`Wait for paste context menu is hidden`);
+ await pasteButtonIsHidden;
+ });
+});
+
+add_task(async function test_context_menu_dimiss_tab_reload() {
+ await BrowserTestUtils.withNewTab(kContentFileUrl, async aBrowser => {
+ info(`Randomized text to avoid overlappings with other tests`);
+ await promiseWritingRandomTextToClipboard();
+
+ info(`Wait for paste context menu is shown`);
+ let pasteButtonIsShown = promisePasteButtonIsShown();
+ await readText(aBrowser);
+ await pasteButtonIsShown;
+
+ info("Reload tab");
+ let pasteButtonIsHidden = promisePasteButtonIsHidden();
+ await BrowserTestUtils.reloadTab(gBrowser.selectedTab);
+
+ info(`Wait for paste context menu is hidden`);
+ await pasteButtonIsHidden;
+ });
+});
diff --git a/toolkit/modules/ClipboardContextMenu.sys.mjs b/toolkit/modules/ClipboardContextMenu.sys.mjs
@@ -164,6 +164,7 @@ export var ClipboardContextMenu = {
let menupopup = aChromeDoc.createXULElement("menupopup");
menupopup.id = this.MENU_POPUP_ID;
menupopup.setAttribute("tabspecific", "true");
+ menupopup.setAttribute("locationspecific", "true");
menupopup.appendChild(menuitem);
return menupopup;
},