Backed out changeset 796f3bfbaa2d (bug 1476097) for perma dt failures in devtools/client/debugger/new/test/mochitest/browser_dbg-breakpoints-actions.js CLOSED TREE
authorMargareta Eliza Balazs <ebalazs@mozilla.com>
Tue, 30 Oct 2018 14:27:52 +0200
changeset 443552 513d18d84b8270c12da05ec90c2886f601f885cb
parent 443551 373660eb34c8a9d0fbc7ad0ad2874fbd2cb32c6b
child 443553 3de9eb154921289250e04fdd3f4a5a2be4f8a7f0
push id109412
push useraciure@mozilla.com
push dateTue, 30 Oct 2018 22:16:54 +0000
treeherdermozilla-inbound@d751dd2cd337 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1476097
milestone65.0a1
backs out796f3bfbaa2db4fba707e3bb2c3c1160e46c354b
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out changeset 796f3bfbaa2d (bug 1476097) for perma dt failures in devtools/client/debugger/new/test/mochitest/browser_dbg-breakpoints-actions.js CLOSED TREE
devtools/client/framework/moz.build
devtools/client/framework/test/browser_menu_api.js
devtools/client/framework/test/browser_toolbox_textbox_context_menu.js
devtools/client/framework/toolbox-context-menu.js
devtools/client/framework/toolbox.js
devtools/client/framework/toolbox.xul
devtools/client/inspector/computed/test/browser_computed_search-filter_context-menu.js
devtools/client/inspector/rules/test/browser_rules_search-filter_context-menu.js
devtools/client/inspector/test/browser_inspector_search-filter_context-menu.js
devtools/client/inspector/test/browser_inspector_textbox-menu.js
devtools/client/jar.mn
devtools/client/webconsole/components/JSTerm.js
devtools/client/webconsole/utils/context-menu.js
devtools/client/webconsole/webconsole-output-wrapper.js
toolkit/locales/en-US/toolkit/main-window/editmenu.ftl
--- a/devtools/client/framework/moz.build
+++ b/devtools/client/framework/moz.build
@@ -22,17 +22,16 @@ DevToolsModules(
     'gDevTools.jsm',
     'menu-item.js',
     'menu.js',
     'selection.js',
     'sidebar.js',
     'source-map-url-service.js',
     'target-from-url.js',
     'target.js',
-    'toolbox-context-menu.js',
     'toolbox-highlighter-utils.js',
     'toolbox-host-manager.js',
     'toolbox-hosts.js',
     'toolbox-options.js',
     'toolbox-tabs-order-manager.js',
     'toolbox.js',
     'ToolboxProcess.jsm',
 )
--- a/devtools/client/framework/test/browser_menu_api.js
+++ b/devtools/client/framework/test/browser_menu_api.js
@@ -61,17 +61,17 @@ async function testMenuPopup(toolbox) {
       label: "Radio Item",
       type: "radio",
     }),
     new MenuItem({
       label: "Disabled Item",
       disabled: true,
     }),
     new MenuItem({
-      l10nID: "editmenu-undo",
+      l10nID: "foo",
     }),
   ];
 
   for (const item of MENU_ITEMS) {
     menu.append(item);
   }
 
   // Append an invisible MenuItem, which shouldn't show up in the DOM
@@ -127,17 +127,17 @@ async function testSubmenu(toolbox) {
   submenu.append(new MenuItem({
     label: "Submenu item",
     click: () => {
       info("Click callback has fired for submenu item");
       clickFired = true;
     },
   }));
   menu.append(new MenuItem({
-    l10nID: "editmenu-copy",
+    l10nID: "submenu-parent",
     submenu: submenu,
   }));
   menu.append(new MenuItem({
     label: "Submenu parent with attributes",
     id: "submenu-parent-with-attrs",
     submenu: submenu,
     accesskey: "A",
     disabled: true,
@@ -147,17 +147,17 @@ async function testSubmenu(toolbox) {
   ok(toolbox.doc.querySelector("#menu-popup"), "A popup is in the DOM");
   is(toolbox.doc.querySelectorAll("#menu-popup > menuitem").length, 0,
     "No menuitem children");
 
   const menus = toolbox.doc.querySelectorAll("#menu-popup > menu");
   is(menus.length, 2, "Correct number of menus");
   ok(!menus[0].hasAttribute("label"), "No label: should be set by localization");
   ok(!menus[0].hasAttribute("disabled"), "Correct disabled state");
-  is(menus[0].getAttribute("data-l10n-id"), "editmenu-copy", "Correct localization attribute");
+  is(menus[0].getAttribute("data-l10n-id"), "submenu-parent", "Correct localization attribute");
 
   is(menus[1].getAttribute("accesskey"), "A", "Correct accesskey");
   ok(menus[1].hasAttribute("disabled"), "Correct disabled state");
   is(menus[1].id, "submenu-parent-with-attrs", "Correct id");
 
   const subMenuItems = menus[0].querySelectorAll("menupopup > menuitem");
   is(subMenuItems.length, 1, "Correct number of submenu items");
   is(subMenuItems[0].getAttribute("label"), "Submenu item", "Correct label");
--- a/devtools/client/framework/test/browser_toolbox_textbox_context_menu.js
+++ b/devtools/client/framework/test/browser_toolbox_textbox_context_menu.js
@@ -14,53 +14,50 @@ const textboxToolId = "testtool1";
 
 registerCleanupFunction(() => {
   gDevTools.unregisterTool(textboxToolId);
 });
 
 add_task(async function checkMenuEntryStates() {
   info("Checking the state of edit menuitems with an empty clipboard");
   const toolbox = await openNewTabAndToolbox(URL, "inspector");
+  const textboxContextMenu = toolbox.textBoxContextMenuPopup;
 
   emptyClipboard();
 
   // Make sure the focus is predictable.
   const inspector = toolbox.getPanel("inspector");
   const onFocus = once(inspector.searchBox, "focus");
   inspector.searchBox.focus();
   await onFocus;
 
-  info("Opening context menu");
-  const onContextMenuPopup = toolbox.once("menu-open");
-  synthesizeContextMenuEvent(inspector.searchBox);
-  await onContextMenuPopup;
-
-  const textboxContextMenu = toolbox.doc.getElementById("toolbox-menu");
   ok(textboxContextMenu, "The textbox context menu is loaded in the toolbox");
 
-  const cmdUndo = textboxContextMenu.querySelector("#editmenu-undo");
-  const cmdDelete = textboxContextMenu.querySelector("#editmenu-delete");
-  const cmdSelectAll = textboxContextMenu.querySelector("#editmenu-selectAll");
-  const cmdCut = textboxContextMenu.querySelector("#editmenu-cut");
-  const cmdCopy = textboxContextMenu.querySelector("#editmenu-copy");
-  const cmdPaste = textboxContextMenu.querySelector("#editmenu-paste");
+  const cmdUndo = textboxContextMenu.querySelector("[command=cmd_undo]");
+  const cmdDelete = textboxContextMenu.querySelector("[command=cmd_delete]");
+  const cmdSelectAll = textboxContextMenu.querySelector("[command=cmd_selectAll]");
+  const cmdCut = textboxContextMenu.querySelector("[command=cmd_cut]");
+  const cmdCopy = textboxContextMenu.querySelector("[command=cmd_copy]");
+  const cmdPaste = textboxContextMenu.querySelector("[command=cmd_paste]");
+
+  info("Opening context menu");
+
+  const onContextMenuPopup = once(textboxContextMenu, "popupshowing");
+  textboxContextMenu.openPopupAtScreen(0, 0, true);
+  await onContextMenuPopup;
 
   is(cmdUndo.getAttribute("disabled"), "true", "cmdUndo is disabled");
   is(cmdDelete.getAttribute("disabled"), "true", "cmdDelete is disabled");
   is(cmdSelectAll.getAttribute("disabled"), "true", "cmdSelectAll is disabled");
 
   // Cut/Copy/Paste items are enabled in context menu even if there
   // is no selection. See also Bug 1303033, and 1317322
   is(cmdCut.getAttribute("disabled"), "", "cmdCut is enabled");
   is(cmdCopy.getAttribute("disabled"), "", "cmdCopy is enabled");
   is(cmdPaste.getAttribute("disabled"), "", "cmdPaste is enabled");
-
-  const onContextMenuHidden = toolbox.once("menu-close");
-  EventUtils.sendKey("ESCAPE", toolbox.win);
-  await onContextMenuHidden;
 });
 
 add_task(async function automaticallyBindTexbox() {
   info("Registering a tool with an input field and making sure the context menu works");
   gDevTools.registerTool({
     id: textboxToolId,
     isTargetSupported: () => true,
     url: `data:text/html;charset=utf8,<input /><input type='text' />
@@ -78,44 +75,40 @@ add_task(async function automaticallyBin
   const doc = toolbox.getCurrentPanel().document;
   await checkTextBox(doc.querySelector("input[type=text]"), toolbox);
   await checkTextBox(doc.querySelector("textarea"), toolbox);
   await checkTextBox(doc.querySelector("input[type=search]"), toolbox);
   await checkTextBox(doc.querySelector("input:not([type])"), toolbox);
   await checkNonTextInput(doc.querySelector("input[type=radio]"), toolbox);
 });
 
-async function checkNonTextInput(input, toolbox) {
-  let textboxContextMenu = toolbox.doc.getElementById("toolbox-menu");
-  ok(!textboxContextMenu, "The menu is closed");
+async function checkNonTextInput(input, {textBoxContextMenuPopup}) {
+  is(textBoxContextMenuPopup.state, "closed", "The menu is closed");
 
   info("Simulating context click on the non text input and expecting no menu to open");
   const eventBubbledUp = new Promise(resolve => {
     input.ownerDocument.addEventListener("contextmenu", resolve, { once: true });
   });
-  synthesizeContextMenuEvent(input);
+  EventUtils.synthesizeMouse(input, 2, 2, {type: "contextmenu", button: 2},
+                             input.ownerDocument.defaultView);
   info("Waiting for event");
   await eventBubbledUp;
-
-  textboxContextMenu = toolbox.doc.getElementById("toolbox-menu");
-  ok(!textboxContextMenu, "The menu is still closed");
+  is(textBoxContextMenuPopup.state, "closed", "The menu is still closed");
 }
 
-async function checkTextBox(textBox, toolbox) {
-  let textboxContextMenu = toolbox.doc.getElementById("toolbox-menu");
-  ok(!textboxContextMenu, "The menu is closed");
+async function checkTextBox(textBox, {textBoxContextMenuPopup}) {
+  is(textBoxContextMenuPopup.state, "closed", "The menu is closed");
 
   info("Simulating context click on the textbox and expecting the menu to open");
-  const onContextMenu = toolbox.once("menu-open");
-  synthesizeContextMenuEvent(textBox);
+  const onContextMenu = once(textBoxContextMenuPopup, "popupshown");
+  EventUtils.synthesizeMouse(textBox, 2, 2, {type: "contextmenu", button: 2},
+                             textBox.ownerDocument.defaultView);
   await onContextMenu;
 
-  textboxContextMenu = toolbox.doc.getElementById("toolbox-menu");
-  ok(textboxContextMenu, "The menu is now visible");
+  is(textBoxContextMenuPopup.state, "open", "The menu is now visible");
 
   info("Closing the menu");
-  const onContextMenuHidden = toolbox.once("menu-close");
-  EventUtils.sendKey("ESCAPE", toolbox.win);
+  const onContextMenuHidden = once(textBoxContextMenuPopup, "popuphidden");
+  textBoxContextMenuPopup.hidePopup();
   await onContextMenuHidden;
 
-  textboxContextMenu = toolbox.doc.getElementById("toolbox-menu");
-  ok(!textboxContextMenu, "The menu is closed again");
+  is(textBoxContextMenuPopup.state, "closed", "The menu is closed again");
 }
deleted file mode 100644
--- a/devtools/client/framework/toolbox-context-menu.js
+++ /dev/null
@@ -1,103 +0,0 @@
-/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
-/* vim: set ft=javascript ts=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 Menu = require("devtools/client/framework/menu");
-const MenuItem = require("devtools/client/framework/menu-item");
-
-var stringsLoaded = false;
-
-/**
- * Lazily load strings for the edit menu.
- */
-function loadEditMenuStrings(win) {
-  if (stringsLoaded) {
-    return;
-  }
-
-  if (typeof win.MozXULElement !== "undefined") {
-    stringsLoaded = true;
-    win.MozXULElement.insertFTLIfNeeded("toolkit/main-window/editmenu.ftl");
-  }
-}
-
-/**
- * Return an 'edit' menu for a input field. This integrates directly
- * with docshell commands to provide the right enabled state and editor
- * functionality.
- *
- * You'll need to call menu.popup() yourself, this just returns the Menu instance.
- *
- * @param {Window} win parent window reference
- * @param {String} id menu ID
- *
- * @returns {Menu}
- */
-function createEditContextMenu(win, id) {
-  // Localized strings for the menu are loaded lazily.
-  loadEditMenuStrings(win);
-
-  const docshell = win.docShell;
-  const menu = new Menu({id});
-  menu.append(new MenuItem({
-    id: "editmenu-undo",
-    l10nID: "editmenu-undo",
-    disabled: !docshell.isCommandEnabled("cmd_undo"),
-    click: () => {
-      docshell.doCommand("cmd_undo");
-    },
-  }));
-  menu.append(new MenuItem({
-    type: "separator",
-  }));
-  menu.append(new MenuItem({
-    id: "editmenu-cut",
-    l10nID: "editmenu-cut",
-    disabled: !docshell.isCommandEnabled("cmd_cut"),
-    click: () => {
-      docshell.doCommand("cmd_cut");
-    },
-  }));
-  menu.append(new MenuItem({
-    id: "editmenu-copy",
-    l10nID: "editmenu-copy",
-    disabled: !docshell.isCommandEnabled("cmd_copy"),
-    click: () => {
-      docshell.doCommand("cmd_copy");
-    },
-  }));
-  menu.append(new MenuItem({
-    id: "editmenu-paste",
-    l10nID: "editmenu-paste",
-    disabled: !docshell.isCommandEnabled("cmd_paste"),
-    click: () => {
-      docshell.doCommand("cmd_paste");
-    },
-  }));
-  menu.append(new MenuItem({
-    id: "editmenu-delete",
-    l10nID: "editmenu-delete",
-    disabled: !docshell.isCommandEnabled("cmd_delete"),
-    click: () => {
-      docshell.doCommand("cmd_delete");
-    },
-  }));
-  menu.append(new MenuItem({
-    type: "separator",
-  }));
-  menu.append(new MenuItem({
-    id: "editmenu-selectAll",
-    l10nID: "editmenu-select-all",
-    disabled: !docshell.isCommandEnabled("cmd_selectAll"),
-    click: () => {
-      docshell.doCommand("cmd_selectAll");
-    },
-  }));
-  return menu;
-}
-
-module.exports.createEditContextMenu = createEditContextMenu;
--- a/devtools/client/framework/toolbox.js
+++ b/devtools/client/framework/toolbox.js
@@ -60,18 +60,16 @@ loader.lazyRequireGetter(this, "HUDServi
 loader.lazyRequireGetter(this, "viewSource",
   "devtools/client/shared/view-source");
 loader.lazyRequireGetter(this, "buildHarLog",
   "devtools/client/netmonitor/src/har/har-builder-utils", true);
 loader.lazyRequireGetter(this, "NetMonitorAPI",
   "devtools/client/netmonitor/src/api", true);
 loader.lazyRequireGetter(this, "sortPanelDefinitions",
   "devtools/client/framework/toolbox-tabs-order-manager", true);
-loader.lazyRequireGetter(this, "createEditContextMenu",
-  "devtools/client/framework/toolbox-context-menu", true);
 
 loader.lazyGetter(this, "domNodeConstants", () => {
   return require("devtools/shared/dom-node-constants");
 });
 
 loader.lazyGetter(this, "registerHarOverlay", () => {
   return require("devtools/client/netmonitor/src/har/toolbox-overlay").register;
 });
@@ -468,16 +466,20 @@ Toolbox.prototype = {
       this.isReady = true;
 
       const framesPromise = this._listFrames();
 
       Services.prefs.addObserver("devtools.cache.disabled", this._applyCacheSettings);
       Services.prefs.addObserver("devtools.serviceWorkers.testing.enabled",
                                  this._applyServiceWorkersTestingSettings);
 
+      this.textBoxContextMenuPopup =
+        this.doc.getElementById("toolbox-textbox-context-popup");
+      this.textBoxContextMenuPopup.addEventListener("popupshowing",
+        this._updateTextBoxMenuItems, true);
       this.doc.addEventListener("contextmenu", (e) => {
         if (e.originalTarget.closest("input[type=text]") ||
             e.originalTarget.closest("input[type=search]") ||
             e.originalTarget.closest("input:not([type])") ||
             e.originalTarget.closest("textarea")) {
           e.stopPropagation();
           e.preventDefault();
           this.openTextBoxContextMenu(e.screenX, e.screenY);
@@ -2865,16 +2867,21 @@ Toolbox.prototype = {
     }
 
     if (this.webconsolePanel) {
       this._saveSplitConsoleHeight();
       this.webconsolePanel.removeEventListener("resize",
         this._saveSplitConsoleHeight);
       this.webconsolePanel = null;
     }
+    if (this.textBoxContextMenuPopup) {
+      this.textBoxContextMenuPopup.removeEventListener("popupshowing",
+        this._updateTextBoxMenuItems, true);
+      this.textBoxContextMenuPopup = null;
+    }
     if (this._componentMount) {
       this._componentMount.removeEventListener("keypress", this._onToolbarArrowKeypress);
       this.ReactDOM.unmountComponentAtNode(this._componentMount);
       this._componentMount = null;
     }
 
     const outstanding = [];
     for (const [id, panel] of this._toolPanels) {
@@ -3028,23 +3035,17 @@ Toolbox.prototype = {
   /**
    * Open the textbox context menu at given coordinates.
    * Panels in the toolbox can call this on contextmenu events with event.screenX/Y
    * instead of having to implement their own copy/paste/selectAll menu.
    * @param {Number} x
    * @param {Number} y
    */
   openTextBoxContextMenu: function(x, y) {
-    const menu = createEditContextMenu(this.win, "toolbox-menu");
-
-    // Fire event for tests
-    menu.once("open", () => this.emit("menu-open"));
-    menu.once("close", () => this.emit("menu-close"));
-
-    menu.popup(x, y, { doc: this.doc });
+    this.textBoxContextMenuPopup.openPopupAtScreen(x, y, true);
   },
 
   /**
    * Connects to the Gecko Profiler when the developer tools are open. This is
    * necessary because of the WebConsole's `profile` and `profileEnd` methods.
    */
   async initPerformance() {
     // If target does not have performance actor (addons), do not
--- a/devtools/client/framework/toolbox.xul
+++ b/devtools/client/framework/toolbox.xul
@@ -4,33 +4,56 @@
    - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
 <?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
 <?xml-stylesheet href="chrome://devtools/skin/toolbox.css" type="text/css"?>
 <?xml-stylesheet href="resource://devtools/client/shared/components/NotificationBox.css" type="text/css"?>
 
 <!DOCTYPE window [
 <!ENTITY % toolboxDTD SYSTEM "chrome://devtools/locale/toolbox.dtd" >
 %toolboxDTD;
+<!ENTITY % editMenuStrings SYSTEM "chrome://global/locale/editMenuOverlay.dtd">
+%editMenuStrings;
 <!ENTITY % globalKeysDTD SYSTEM "chrome://global/locale/globalKeys.dtd">
 %globalKeysDTD;
 ]>
 
 <window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
         xmlns:html="http://www.w3.org/1999/xhtml">
 
   <script type="application/javascript"
           src="chrome://devtools/content/shared/theme-switching.js"/>
   <script type="application/javascript"
           src="chrome://global/content/viewSourceUtils.js"/>
 
-  <script type="application/javascript"
-          src="chrome://global/content/globalOverlay.js"/>
+  <script type="application/javascript" src="chrome://global/content/globalOverlay.js"/>
   <script type="application/javascript"
           src="chrome://devtools/content/framework/toolbox-init.js"/>
 
+#include ../../../toolkit/content/editMenuCommands.inc.xul
+#include ../../../toolkit/content/editMenuKeys.inc.xul
+
+  <popupset>
+    <menupopup id="toolbox-textbox-context-popup">
+      <menuitem id="cMenu_undo" label="&undoCmd.label;"
+                accesskey="&undoCmd.accesskey;" command="cmd_undo"/>
+      <menuseparator/>
+      <menuitem id="cMenu_cut" label="&cutCmd.label;"
+                accesskey="&cutCmd.accesskey;" command="cmd_cut"/>
+      <menuitem id="cMenu_copy" label="&copyCmd.label;"
+                accesskey="&copyCmd.accesskey;" command="cmd_copy"/>
+      <menuitem id="cMenu_paste" label="&pasteCmd.label;"
+                accesskey="&pasteCmd.accesskey;" command="cmd_paste"/>
+      <menuitem id="cMenu_delete" label="&deleteCmd.label;"
+                accesskey="&deleteCmd.accesskey;" command="cmd_delete"/>
+      <menuseparator/>
+      <menuitem id="cMenu_selectAll" label="&selectAllCmd.label;"
+                accesskey="&selectAllCmd.accesskey;" command="cmd_selectAll"/>
+    </menupopup>
+  </popupset>
+
   <vbox id="toolbox-container" flex="1">
     <div xmlns="http://www.w3.org/1999/xhtml" id="toolbox-notificationbox"/>
     <div xmlns="http://www.w3.org/1999/xhtml" id="toolbox-toolbar-mount"
          role="toolbar" />
     <vbox flex="1" class="theme-body">
       <!-- Set large flex to allow the toolbox-panel-webconsole to have a
            height set to a small value without flexing to fill up extra
            space. There must be a flex on both to ensure that the console
--- a/devtools/client/inspector/computed/test/browser_computed_search-filter_context-menu.js
+++ b/devtools/client/inspector/computed/test/browser_computed_search-filter_context-menu.js
@@ -10,89 +10,71 @@ const TEST_INPUT = "h1";
 
 const TEST_URI = "<h1>test filter context menu</h1>";
 
 add_task(async function() {
   await addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
   const {toolbox, inspector, view} = await openComputedView();
   await selectNode("h1", inspector);
 
+  const win = view.styleWindow;
   const searchField = view.searchField;
+  const searchContextMenu = toolbox.textBoxContextMenuPopup;
+  ok(searchContextMenu,
+    "The search filter context menu is loaded in the computed view");
+
+  const cmdUndo = searchContextMenu.querySelector("[command=cmd_undo]");
+  const cmdDelete = searchContextMenu.querySelector("[command=cmd_delete]");
+  const cmdSelectAll = searchContextMenu.querySelector("[command=cmd_selectAll]");
+  const cmdCut = searchContextMenu.querySelector("[command=cmd_cut]");
+  const cmdCopy = searchContextMenu.querySelector("[command=cmd_copy]");
+  const cmdPaste = searchContextMenu.querySelector("[command=cmd_paste]");
 
   info("Opening context menu");
 
   emptyClipboard();
 
   const onFocus = once(searchField, "focus");
   searchField.focus();
   await onFocus;
 
-  let onContextMenuOpen = toolbox.once("menu-open");
-  synthesizeContextMenuEvent(searchField);
-  await onContextMenuOpen;
-
-  let searchContextMenu = toolbox.doc.getElementById("toolbox-menu");
-  ok(searchContextMenu,
-    "The search filter context menu is loaded in the computed view");
-
-  let cmdUndo = searchContextMenu.querySelector("#editmenu-undo");
-  let cmdDelete = searchContextMenu.querySelector("#editmenu-delete");
-  let cmdSelectAll = searchContextMenu.querySelector("#editmenu-selectAll");
-  let cmdCut = searchContextMenu.querySelector("#editmenu-cut");
-  let cmdCopy = searchContextMenu.querySelector("#editmenu-copy");
-  let cmdPaste = searchContextMenu.querySelector("#editmenu-paste");
+  const onContextMenuPopup = once(searchContextMenu, "popupshowing");
+  EventUtils.synthesizeMouse(searchField, 2, 2,
+    {type: "contextmenu", button: 2}, win);
+  await onContextMenuPopup;
 
   is(cmdUndo.getAttribute("disabled"), "true", "cmdUndo is disabled");
   is(cmdDelete.getAttribute("disabled"), "true", "cmdDelete is disabled");
   is(cmdSelectAll.getAttribute("disabled"), "true", "cmdSelectAll is disabled");
 
   // Cut/Copy/Paste items are enabled in context menu even if there is no
   // selection. See also Bug 1303033, and 1317322
   is(cmdCut.getAttribute("disabled"), "", "cmdCut is enabled");
   is(cmdCopy.getAttribute("disabled"), "", "cmdCopy is enabled");
   is(cmdPaste.getAttribute("disabled"), "", "cmdPaste is enabled");
 
   info("Closing context menu");
-  let onContextMenuClose = toolbox.once("menu-close");
-  EventUtils.sendKey("ESCAPE", toolbox.win);
-  await onContextMenuClose;
+  const onContextMenuHidden = once(searchContextMenu, "popuphidden");
+  searchContextMenu.hidePopup();
+  await onContextMenuHidden;
 
   info("Copy text in search field using the context menu");
   searchField.setUserInput(TEST_INPUT);
   searchField.select();
-
-  onContextMenuOpen = toolbox.once("menu-open");
-  synthesizeContextMenuEvent(searchField);
-  await onContextMenuOpen;
-
-  searchContextMenu = toolbox.doc.getElementById("toolbox-menu");
-  cmdCopy = searchContextMenu.querySelector("#editmenu-copy");
+  EventUtils.synthesizeMouse(searchField, 2, 2,
+    {type: "contextmenu", button: 2}, win);
+  await onContextMenuPopup;
   await waitForClipboardPromise(() => cmdCopy.click(), TEST_INPUT);
-
-  onContextMenuClose = toolbox.once("menu-close");
-  EventUtils.sendKey("ESCAPE", toolbox.win);
-  await onContextMenuClose;
+  searchContextMenu.hidePopup();
+  await onContextMenuHidden;
 
   info("Reopen context menu and check command properties");
-
-  onContextMenuOpen = toolbox.once("menu-open");
-  synthesizeContextMenuEvent(searchField);
-  await onContextMenuOpen;
-
-  searchContextMenu = toolbox.doc.getElementById("toolbox-menu");
-  cmdUndo = searchContextMenu.querySelector("#editmenu-undo");
-  cmdDelete = searchContextMenu.querySelector("#editmenu-delete");
-  cmdSelectAll = searchContextMenu.querySelector("#editmenu-selectAll");
-  cmdCut = searchContextMenu.querySelector("#editmenu-cut");
-  cmdCopy = searchContextMenu.querySelector("#editmenu-copy");
-  cmdPaste = searchContextMenu.querySelector("#editmenu-paste");
+  EventUtils.synthesizeMouse(searchField, 2, 2,
+    {type: "contextmenu", button: 2}, win);
+  await onContextMenuPopup;
 
   is(cmdUndo.getAttribute("disabled"), "", "cmdUndo is enabled");
   is(cmdDelete.getAttribute("disabled"), "", "cmdDelete is enabled");
   is(cmdSelectAll.getAttribute("disabled"), "", "cmdSelectAll is enabled");
   is(cmdCut.getAttribute("disabled"), "", "cmdCut is enabled");
   is(cmdCopy.getAttribute("disabled"), "", "cmdCopy is enabled");
   is(cmdPaste.getAttribute("disabled"), "", "cmdPaste is enabled");
-
-  onContextMenuClose = toolbox.once("menu-close");
-  EventUtils.sendKey("ESCAPE", toolbox.win);
-  await onContextMenuClose;
 });
--- a/devtools/client/inspector/rules/test/browser_rules_search-filter_context-menu.js
+++ b/devtools/client/inspector/rules/test/browser_rules_search-filter_context-menu.js
@@ -9,89 +9,71 @@
 const TEST_INPUT = "h1";
 const TEST_URI = "<h1>test filter context menu</h1>";
 
 add_task(async function() {
   await addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
   const {toolbox, inspector, view} = await openRuleView();
   await selectNode("h1", inspector);
 
+  const win = view.styleWindow;
   const searchField = view.searchField;
+  const searchContextMenu = toolbox.textBoxContextMenuPopup;
+  ok(searchContextMenu,
+    "The search filter context menu is loaded in the rule view");
+
+  const cmdUndo = searchContextMenu.querySelector("[command=cmd_undo]");
+  const cmdDelete = searchContextMenu.querySelector("[command=cmd_delete]");
+  const cmdSelectAll = searchContextMenu.querySelector("[command=cmd_selectAll]");
+  const cmdCut = searchContextMenu.querySelector("[command=cmd_cut]");
+  const cmdCopy = searchContextMenu.querySelector("[command=cmd_copy]");
+  const cmdPaste = searchContextMenu.querySelector("[command=cmd_paste]");
 
   info("Opening context menu");
 
   emptyClipboard();
 
   const onFocus = once(searchField, "focus");
   searchField.focus();
   await onFocus;
 
-  let onContextMenuOpen = toolbox.once("menu-open");
-  synthesizeContextMenuEvent(searchField);
-  await onContextMenuOpen;
-
-  let searchContextMenu = toolbox.doc.getElementById("toolbox-menu");
-  ok(searchContextMenu,
-    "The search filter context menu is loaded in the rule view");
-
-  let cmdUndo = searchContextMenu.querySelector("#editmenu-undo");
-  let cmdDelete = searchContextMenu.querySelector("#editmenu-delete");
-  let cmdSelectAll = searchContextMenu.querySelector("#editmenu-selectAll");
-  let cmdCut = searchContextMenu.querySelector("#editmenu-cut");
-  let cmdCopy = searchContextMenu.querySelector("#editmenu-copy");
-  let cmdPaste = searchContextMenu.querySelector("#editmenu-paste");
+  const onContextMenuPopup = once(searchContextMenu, "popupshowing");
+  EventUtils.synthesizeMouse(searchField, 2, 2,
+    {type: "contextmenu", button: 2}, win);
+  await onContextMenuPopup;
 
   is(cmdUndo.getAttribute("disabled"), "true", "cmdUndo is disabled");
   is(cmdDelete.getAttribute("disabled"), "true", "cmdDelete is disabled");
   is(cmdSelectAll.getAttribute("disabled"), "true", "cmdSelectAll is disabled");
 
   // Cut/Copy/Paste items are enabled in context menu even if there is no
   // selection. See also Bug 1303033, and 1317322
   is(cmdCut.getAttribute("disabled"), "", "cmdCut is enabled");
   is(cmdCopy.getAttribute("disabled"), "", "cmdCopy is enabled");
   is(cmdPaste.getAttribute("disabled"), "", "cmdPaste is enabled");
 
   info("Closing context menu");
-  let onContextMenuClose = toolbox.once("menu-close");
-  EventUtils.sendKey("ESCAPE", toolbox.win);
-  await onContextMenuClose;
+  const onContextMenuHidden = once(searchContextMenu, "popuphidden");
+  searchContextMenu.hidePopup();
+  await onContextMenuHidden;
 
   info("Copy text in search field using the context menu");
   searchField.setUserInput(TEST_INPUT);
   searchField.select();
-
-  onContextMenuOpen = toolbox.once("menu-open");
-  synthesizeContextMenuEvent(searchField);
-  await onContextMenuOpen;
-
-  searchContextMenu = toolbox.doc.getElementById("toolbox-menu");
-  cmdCopy = searchContextMenu.querySelector("#editmenu-copy");
+  EventUtils.synthesizeMouse(searchField, 2, 2,
+    {type: "contextmenu", button: 2}, win);
+  await onContextMenuPopup;
   await waitForClipboardPromise(() => cmdCopy.click(), TEST_INPUT);
-
-  onContextMenuClose = toolbox.once("menu-close");
-  EventUtils.sendKey("ESCAPE", toolbox.win);
-  await onContextMenuClose;
+  searchContextMenu.hidePopup();
+  await onContextMenuHidden;
 
   info("Reopen context menu and check command properties");
-
-  onContextMenuOpen = toolbox.once("menu-open");
-  synthesizeContextMenuEvent(searchField);
-  await onContextMenuOpen;
-
-  searchContextMenu = toolbox.doc.getElementById("toolbox-menu");
-  cmdUndo = searchContextMenu.querySelector("#editmenu-undo");
-  cmdDelete = searchContextMenu.querySelector("#editmenu-delete");
-  cmdSelectAll = searchContextMenu.querySelector("#editmenu-selectAll");
-  cmdCut = searchContextMenu.querySelector("#editmenu-cut");
-  cmdCopy = searchContextMenu.querySelector("#editmenu-copy");
-  cmdPaste = searchContextMenu.querySelector("#editmenu-paste");
+  EventUtils.synthesizeMouse(searchField, 2, 2,
+    {type: "contextmenu", button: 2}, win);
+  await onContextMenuPopup;
 
   is(cmdUndo.getAttribute("disabled"), "", "cmdUndo is enabled");
   is(cmdDelete.getAttribute("disabled"), "", "cmdDelete is enabled");
   is(cmdSelectAll.getAttribute("disabled"), "", "cmdSelectAll is enabled");
   is(cmdCut.getAttribute("disabled"), "", "cmdCut is enabled");
   is(cmdCopy.getAttribute("disabled"), "", "cmdCopy is enabled");
   is(cmdPaste.getAttribute("disabled"), "", "cmdPaste is enabled");
-
-  const onContextMenuHidden = toolbox.once("menu-close");
-  EventUtils.sendKey("ESCAPE", toolbox.win);
-  await onContextMenuHidden;
 });
--- a/devtools/client/inspector/test/browser_inspector_search-filter_context-menu.js
+++ b/devtools/client/inspector/test/browser_inspector_search-filter_context-menu.js
@@ -9,91 +9,74 @@ const TEST_INPUT = "h1";
 const TEST_URI = "<h1>test filter context menu</h1>";
 
 add_task(async function() {
   await addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
   const {toolbox, inspector} = await openInspector();
   const {searchBox} = inspector;
   await selectNode("h1", inspector);
 
+  const win = inspector.panelWin;
+  const searchContextMenu = toolbox.textBoxContextMenuPopup;
+  ok(searchContextMenu,
+    "The search filter context menu is loaded in the inspector");
+
+  const cmdUndo = searchContextMenu.querySelector("[command=cmd_undo]");
+  const cmdDelete = searchContextMenu.querySelector("[command=cmd_delete]");
+  const cmdSelectAll = searchContextMenu.querySelector("[command=cmd_selectAll]");
+  const cmdCut = searchContextMenu.querySelector("[command=cmd_cut]");
+  const cmdCopy = searchContextMenu.querySelector("[command=cmd_copy]");
+  const cmdPaste = searchContextMenu.querySelector("[command=cmd_paste]");
+
   emptyClipboard();
 
   info("Opening context menu");
   const onFocus = once(searchBox, "focus");
   searchBox.focus();
   await onFocus;
 
-  let onContextMenuOpen = toolbox.once("menu-open");
-  synthesizeContextMenuEvent(searchBox);
-  await onContextMenuOpen;
-
-  let searchContextMenu = toolbox.doc.getElementById("toolbox-menu");
-  ok(searchContextMenu,
-    "The search filter context menu is loaded in the computed view");
-
-  let cmdUndo = searchContextMenu.querySelector("#editmenu-undo");
-  let cmdDelete = searchContextMenu.querySelector("#editmenu-delete");
-  let cmdSelectAll = searchContextMenu.querySelector("#editmenu-selectAll");
-  let cmdCut = searchContextMenu.querySelector("#editmenu-cut");
-  let cmdCopy = searchContextMenu.querySelector("#editmenu-copy");
-  let cmdPaste = searchContextMenu.querySelector("#editmenu-paste");
+  const onContextMenuPopup = once(searchContextMenu, "popupshowing");
+  EventUtils.synthesizeMouse(searchBox, 2, 2,
+    {type: "contextmenu", button: 2}, win);
+  await onContextMenuPopup;
 
   is(cmdUndo.getAttribute("disabled"), "true", "cmdUndo is disabled");
   is(cmdDelete.getAttribute("disabled"), "true", "cmdDelete is disabled");
   is(cmdSelectAll.getAttribute("disabled"), "true", "cmdSelectAll is disabled");
 
   // Cut/Copy items are enabled in context menu even if there
   // is no selection. See also Bug 1303033, and 1317322
   is(cmdCut.getAttribute("disabled"), "", "cmdCut is enabled");
   is(cmdCopy.getAttribute("disabled"), "", "cmdCopy is enabled");
   is(cmdPaste.getAttribute("disabled"), "", "cmdPaste is enabled");
 
   info("Closing context menu");
-  let onContextMenuClose = toolbox.once("menu-close");
-  EventUtils.sendKey("ESCAPE", toolbox.win);
-  await onContextMenuClose;
+  const onContextMenuHidden = once(searchContextMenu, "popuphidden");
+  searchContextMenu.hidePopup();
+  await onContextMenuHidden;
 
   info("Copy text in search field using the context menu");
   searchBox.setUserInput(TEST_INPUT);
   searchBox.select();
   searchBox.focus();
-
-  onContextMenuOpen = toolbox.once("menu-open");
-  synthesizeContextMenuEvent(searchBox);
-  await onContextMenuOpen;
-
-  searchContextMenu = toolbox.doc.getElementById("toolbox-menu");
-  cmdCopy = searchContextMenu.querySelector("#editmenu-copy");
+  EventUtils.synthesizeMouse(searchBox, 2, 2,
+    {type: "contextmenu", button: 2}, win);
+  await onContextMenuPopup;
   await waitForClipboardPromise(() => cmdCopy.click(), TEST_INPUT);
-
-  onContextMenuClose = toolbox.once("menu-close");
-  EventUtils.sendKey("ESCAPE", toolbox.win);
-  await onContextMenuClose;
+  searchContextMenu.hidePopup();
+  await onContextMenuHidden;
 
   info("Reopen context menu and check command properties");
-
-  onContextMenuOpen = toolbox.once("menu-open");
-  synthesizeContextMenuEvent(searchBox);
-  await onContextMenuOpen;
-
-  searchContextMenu = toolbox.doc.getElementById("toolbox-menu");
-  cmdUndo = searchContextMenu.querySelector("#editmenu-undo");
-  cmdDelete = searchContextMenu.querySelector("#editmenu-delete");
-  cmdSelectAll = searchContextMenu.querySelector("#editmenu-selectAll");
-  cmdCut = searchContextMenu.querySelector("#editmenu-cut");
-  cmdCopy = searchContextMenu.querySelector("#editmenu-copy");
-  cmdPaste = searchContextMenu.querySelector("#editmenu-paste");
+  EventUtils.synthesizeMouse(searchBox, 2, 2,
+    {type: "contextmenu", button: 2}, win);
+  await onContextMenuPopup;
 
   is(cmdUndo.getAttribute("disabled"), "", "cmdUndo is enabled");
   is(cmdDelete.getAttribute("disabled"), "", "cmdDelete is enabled");
   is(cmdSelectAll.getAttribute("disabled"), "", "cmdSelectAll is enabled");
   is(cmdCut.getAttribute("disabled"), "", "cmdCut is enabled");
   is(cmdCopy.getAttribute("disabled"), "", "cmdCopy is enabled");
   is(cmdPaste.getAttribute("disabled"), "", "cmdPaste is enabled");
 
-  const onContextMenuHidden = toolbox.once("menu-close");
-  EventUtils.sendKey("ESCAPE", toolbox.win);
-  await onContextMenuHidden;
-
   // We have to wait for search query to avoid test failure.
   info("Waiting for search query to complete and getting the suggestions");
   await inspector.searchSuggestions._lastQuery;
 });
--- a/devtools/client/inspector/test/browser_inspector_textbox-menu.js
+++ b/devtools/client/inspector/test/browser_inspector_textbox-menu.js
@@ -75,28 +75,26 @@ add_task(async function() {
   EventUtils.synthesizeMouseAtCenter(margin, {}, inspector.panelWin);
   await checkTextBox(inspector.panelDoc.activeElement, toolbox);
 
   // Move the mouse out of the box-model region to avoid triggering the box model
   // highlighter.
   EventUtils.synthesizeMouseAtCenter(tag, {}, inspector.panelWin);
 });
 
-async function checkTextBox(textBox, toolbox) {
-  let textboxContextMenu = toolbox.doc.getElementById("toolbox-menu");
-  ok(!textboxContextMenu, "The menu is  closed");
+async function checkTextBox(textBox, {textBoxContextMenuPopup}) {
+  is(textBoxContextMenuPopup.state, "closed", "The menu is closed");
 
   info("Simulating context click on the textbox and expecting the menu to open");
-  const onContextMenu = toolbox.once("menu-open");
-  synthesizeContextMenuEvent(textBox);
+  const onContextMenu = once(textBoxContextMenuPopup, "popupshown");
+  EventUtils.synthesizeMouse(textBox, 2, 2, {type: "contextmenu", button: 2},
+                             textBox.ownerDocument.defaultView);
   await onContextMenu;
 
-  textboxContextMenu = toolbox.doc.getElementById("toolbox-menu");
-  ok(textboxContextMenu, "The menu is now visible");
+  is(textBoxContextMenuPopup.state, "open", "The menu is now visible");
 
   info("Closing the menu");
-  const onContextMenuHidden = toolbox.once("menu-close");
-  EventUtils.sendKey("ESCAPE", toolbox.win);
+  const onContextMenuHidden = once(textBoxContextMenuPopup, "popuphidden");
+  textBoxContextMenuPopup.hidePopup();
   await onContextMenuHidden;
 
-  textboxContextMenu = toolbox.doc.getElementById("toolbox-menu");
-  ok(!textboxContextMenu, "The menu is closed again");
+  is(textBoxContextMenuPopup.state, "closed", "The menu is closed again");
 }
--- a/devtools/client/jar.mn
+++ b/devtools/client/jar.mn
@@ -51,17 +51,17 @@ devtools.jar:
     content/performance/views/details-js-call-tree.js (performance/views/details-js-call-tree.js)
     content/performance/views/details-js-flamegraph.js (performance/views/details-js-flamegraph.js)
     content/performance/views/details-memory-call-tree.js (performance/views/details-memory-call-tree.js)
     content/performance/views/details-memory-flamegraph.js (performance/views/details-memory-flamegraph.js)
     content/performance/views/recordings.js (performance/views/recordings.js)
     content/memory/index.xhtml (memory/index.xhtml)
     content/framework/toolbox-window.xul (framework/toolbox-window.xul)
     content/framework/toolbox-options.xhtml (framework/toolbox-options.xhtml)
-    content/framework/toolbox.xul (framework/toolbox.xul)
+*   content/framework/toolbox.xul (framework/toolbox.xul)
     content/framework/toolbox-init.js (framework/toolbox-init.js)
     content/framework/options-panel.css (framework/options-panel.css)
     content/framework/toolbox-process-window.html (framework/toolbox-process-window.html)
     content/framework/toolbox-process-window.css (framework/toolbox-process-window.css)
     content/framework/toolbox-process-window.js (framework/toolbox-process-window.js)
     content/inspector/index.xhtml (inspector/index.xhtml)
     content/framework/connect/connect.xhtml (framework/connect/connect.xhtml)
     content/framework/connect/connect.css (framework/connect/connect.css)
--- a/devtools/client/webconsole/components/JSTerm.js
+++ b/devtools/client/webconsole/components/JSTerm.js
@@ -1574,17 +1574,23 @@ class JSTerm extends Component {
     const doc = this.hud.document;
 
     return new Number(doc.defaultView
       .getComputedStyle(this.inputNode)
       .paddingInlineStart.replace(/[^0-9.]/g, ""));
   }
 
   onContextMenu(e) {
-    this.props.serviceContainer.openEditContextMenu(e);
+    // The toolbox does it's own edit menu handling with
+    // toolbox-textbox-context-popup and friends. For now, fall
+    // back to use that if running inside the toolbox, but use our
+    // own menu when running in the Browser Console (see Bug 1476097).
+    if (this.props.hud.isBrowserConsole) {
+      this.props.serviceContainer.openEditContextMenu(e);
+    }
   }
 
   destroy() {
     this.webConsoleClient.clearNetworkRequests();
     if (this.hud.outputNode) {
       // We do this because it's much faster than letting React handle the ConsoleOutput
       // unmounting.
       this.hud.outputNode.innerHTML = "";
--- a/devtools/client/webconsole/utils/context-menu.js
+++ b/devtools/client/webconsole/utils/context-menu.js
@@ -193,8 +193,81 @@ function createContextMenu(hud, parentNo
       },
     }));
   }
 
   return menu;
 }
 
 exports.createContextMenu = createContextMenu;
+
+/**
+ * Return an 'edit' menu for a input field. This integrates directly
+ * with docshell commands to provide the right enabled state and editor
+ * functionality.
+ *
+ * You'll need to call menu.popup() yourself, this just returns the Menu instance.
+ *
+ * @returns {Menu}
+ */
+function createEditContextMenu() {
+  const docshell = window.docShell;
+  const menu = new Menu({
+    id: "webconsole-menu",
+  });
+  menu.append(new MenuItem({
+    id: "editmenu-undo",
+    l10nID: "editmenu-undo",
+    disabled: !docshell.isCommandEnabled("cmd_undo"),
+    click: () => {
+      docshell.doCommand("cmd_undo");
+    },
+  }));
+  menu.append(new MenuItem({
+    type: "separator",
+  }));
+  menu.append(new MenuItem({
+    id: "editmenu-cut",
+    l10nID: "editmenu-cut",
+    disabled: !docshell.isCommandEnabled("cmd_cut"),
+    click: () => {
+      docshell.doCommand("cmd_cut");
+    },
+  }));
+  menu.append(new MenuItem({
+    id: "editmenu-copy",
+    l10nID: "editmenu-copy",
+    disabled: !docshell.isCommandEnabled("cmd_copy"),
+    click: () => {
+      docshell.doCommand("cmd_copy");
+    },
+  }));
+  menu.append(new MenuItem({
+    id: "editmenu-paste",
+    l10nID: "editmenu-paste",
+    disabled: !docshell.isCommandEnabled("cmd_paste"),
+    click: () => {
+      docshell.doCommand("cmd_paste");
+    },
+  }));
+  menu.append(new MenuItem({
+    id: "editmenu-delete",
+    l10nID: "editmenu-delete",
+    disabled: !docshell.isCommandEnabled("cmd_delete"),
+    click: () => {
+      docshell.doCommand("cmd_delete");
+    },
+  }));
+  menu.append(new MenuItem({
+    type: "separator",
+  }));
+  menu.append(new MenuItem({
+    id: "editmenu-selectAll",
+    l10nID: "editmenu-select-all",
+    disabled: !docshell.isCommandEnabled("cmd_selectAll"),
+    click: () => {
+      docshell.doCommand("cmd_selectAll");
+    },
+  }));
+  return menu;
+}
+
+exports.createEditContextMenu = createEditContextMenu;
--- a/devtools/client/webconsole/webconsole-output-wrapper.js
+++ b/devtools/client/webconsole/webconsole-output-wrapper.js
@@ -5,18 +5,17 @@
 "use strict";
 
 const Services = require("Services");
 const { createElement, createFactory } = require("devtools/client/shared/vendor/react");
 const ReactDOM = require("devtools/client/shared/vendor/react-dom");
 const { Provider } = require("devtools/client/shared/vendor/react-redux");
 
 const actions = require("devtools/client/webconsole/actions/index");
-const { createEditContextMenu } = require("devtools/client/framework/toolbox-context-menu");
-const { createContextMenu } = require("devtools/client/webconsole/utils/context-menu");
+const { createContextMenu, createEditContextMenu } = require("devtools/client/webconsole/utils/context-menu");
 const { configureStore } = require("devtools/client/webconsole/store");
 
 const { isPacketPrivate } = require("devtools/client/webconsole/utils/messages");
 const { getAllMessagesById, getMessage } = require("devtools/client/webconsole/selectors/messages");
 const Telemetry = require("devtools/client/shared/telemetry");
 
 const EventEmitter = require("devtools/shared/event-emitter");
 const App = createFactory(require("devtools/client/webconsole/components/App"));
@@ -160,17 +159,17 @@ WebConsoleOutputWrapper.prototype = {
         menu.once("open", () => this.emit("menu-open"));
         menu.popup(screenX, screenY, { doc: this.owner.chromeWindow.document });
 
         return menu;
       };
 
       serviceContainer.openEditContextMenu = (e) => {
         const { screenX, screenY } = e;
-        const menu = createEditContextMenu(window, "webconsole-menu");
+        const menu = createEditContextMenu();
         // Emit the "menu-open" event for testing.
         menu.once("open", () => this.emit("menu-open"));
         menu.popup(screenX, screenY, { doc: this.owner.chromeWindow.document });
 
         return menu;
       };
 
       if (this.toolbox) {
--- a/toolkit/locales/en-US/toolkit/main-window/editmenu.ftl
+++ b/toolkit/locales/en-US/toolkit/main-window/editmenu.ftl
@@ -1,14 +1,14 @@
 # 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/.
 
 ### This file contains the entities needed for the 'edit' menu
-### It's currently only used for the Browser Console and Developer Toolbox
+### It's currently only used for the Browser Console
 
 editmenu-undo =
     .label = Undo
     .accesskey = U
 
 editmenu-redo =
     .label = Redo
     .accesskey = R