Bug 1378427 - move context menus around, fix flickering in dynamic portion of the overflow menu for photon, r?jaws draft
authorGijs Kruitbosch <gijskruitbosch@gmail.com>
Fri, 07 Jul 2017 15:54:13 +0100
changeset 605342 e6dab0c0dad29cdc472bd63e1cb49a712c4f27a2
parent 605265 a0b5515b13ebfd3220a06fd1cd31f98a9557f031
child 636472 a7af60de94a5719a7fc921389853278cfacda0e2
push id67387
push usergijskruitbosch@gmail.com
push dateFri, 07 Jul 2017 15:53:15 +0000
reviewersjaws
bugs1378427, 1354078
milestone56.0a1
Bug 1378427 - move context menus around, fix flickering in dynamic portion of the overflow menu for photon, r?jaws Apparently the hover state of the combined buttons does not interact well with the menus unless they share the same containing popup/panel. We broke that condition in bug 1354078. The expedient thing is to simply move the popup back, and move it back and forth if/when the photon pref is flipped. When removing the pref, we can simplify this by always putting the menu in the overflow panel. I also noticed that we use the toolbar context menu in the dynamic portion of the overflow panel. This has the same problem, and to fix it I switched us to using the same (panel) context menu in the photon case. Doing this in the non-photon case won't help because the context menu will be in a separate panel (namely the old hamburger panel) entirely. MozReview-Commit-ID: 4neHMukTzHA
browser/components/customizableui/CustomizableUI.jsm
browser/components/customizableui/CustomizeMode.jsm
browser/components/customizableui/content/panelUI.inc.xul
browser/components/customizableui/test/browser_880164_customization_context_menus.js
browser/components/customizableui/test/browser_photon_customization_context_menus.js
--- a/browser/components/customizableui/CustomizableUI.jsm
+++ b/browser/components/customizableui/CustomizableUI.jsm
@@ -307,17 +307,27 @@ var CustomizableUIInternal = {
       legacy: true,
       defaultPlacements: ["addonbar-closebutton", "status-bar"],
       defaultCollapsed: false,
     }, true);
 
     SearchWidgetTracker.init();
   },
 
+  _updatePanelContextMenuLocation(window) {
+    let panelID = gPhotonStructure ? "widget-overflow" : "PanelUI-popup";
+    let contextMenu = window.document.getElementById("customizationPanelItemContextMenu");
+    window.document.getElementById(panelID).appendChild(contextMenu);
+  },
+
   _updateAreasForPhoton() {
+    for (let [win, ] of gBuildWindows) {
+      this._updatePanelContextMenuLocation(win);
+    }
+
     if (gPhotonStructure) {
       if (gAreas.has(CustomizableUI.AREA_PANEL)) {
         this.unregisterArea(CustomizableUI.AREA_PANEL, true);
       }
       this.registerArea(CustomizableUI.AREA_FIXED_OVERFLOW_PANEL, {
         type: CustomizableUI.TYPE_MENU_PANEL,
         defaultPlacements: [],
       }, true);
@@ -858,25 +868,25 @@ var CustomizableUIInternal = {
     gELS.removeSystemEventListener(aPanel, "keypress", this, false);
     let win = aPanel.ownerGlobal;
     let panels = gPanelsForWindow.get(win);
     if (panels) {
       panels.delete(this._getPanelForNode(aPanel));
     }
   },
 
-  ensureButtonContextMenu(aNode, aAreaNode) {
+  ensureButtonContextMenu(aNode, aAreaNode, forcePanel) {
     const kPanelItemContextMenu = "customizationPanelItemContextMenu";
 
     let currentContextMenu = aNode.getAttribute("context") ||
                              aNode.getAttribute("contextmenu");
-    let place = CustomizableUI.getPlaceForItem(aAreaNode);
-    let contextMenuForPlace = place == "panel" ?
-                                kPanelItemContextMenu :
-                                null;
+    let contextMenuForPlace =
+      (forcePanel || "panel" == CustomizableUI.getPlaceForItem(aAreaNode)) ?
+      kPanelItemContextMenu :
+      null;
     if (contextMenuForPlace && !currentContextMenu) {
       aNode.setAttribute("context", contextMenuForPlace);
     } else if (currentContextMenu == kPanelItemContextMenu &&
                contextMenuForPlace != kPanelItemContextMenu) {
       aNode.removeAttribute("context");
       aNode.removeAttribute("contextmenu");
     }
   },
@@ -948,21 +958,21 @@ var CustomizableUIInternal = {
 
     let placements = gPlacements.get(aArea);
     this.buildArea(aArea, placements, aPanelContents);
     this.notifyListeners("onAreaNodeRegistered", aArea, aPanelContents);
 
     for (let child of aPanelContents.children) {
       if (child.localName != "toolbarbutton") {
         if (child.localName == "toolbaritem") {
-          this.ensureButtonContextMenu(child, aPanelContents);
+          this.ensureButtonContextMenu(child, aPanelContents, true);
         }
         continue;
       }
-      this.ensureButtonContextMenu(child, aPanelContents);
+      this.ensureButtonContextMenu(child, aPanelContents, true);
       child.setAttribute("wrap", "true");
     }
 
     this.registerBuildArea(aArea, aPanelContents);
   },
 
   onWidgetAdded(aWidgetId, aArea, aPosition) {
     this.insertNode(aWidgetId, aArea, aPosition, true);
@@ -1069,16 +1079,17 @@ var CustomizableUIInternal = {
   },
 
   registerBuildWindow(aWindow) {
     if (!gBuildWindows.has(aWindow)) {
       gBuildWindows.set(aWindow, new Set());
 
       aWindow.addEventListener("unload", this);
       aWindow.addEventListener("command", this, true);
+      this._updatePanelContextMenuLocation(aWindow);
 
       this.notifyListeners("onWindowOpened", aWindow);
     }
   },
 
   unregisterBuildWindow(aWindow) {
     aWindow.removeEventListener("unload", this);
     aWindow.removeEventListener("command", this, true);
@@ -4251,16 +4262,17 @@ OverflowableToolbar.prototype = {
 
     while (child && this._target.scrollLeftMin != this._target.scrollLeftMax) {
       let prevChild = child.previousSibling;
 
       if (child.getAttribute("overflows") != "false") {
         this._collapsed.set(child.id, this._target.clientWidth);
         child.setAttribute("overflowedItem", true);
         child.setAttribute("cui-anchorid", this._chevron.id);
+        CustomizableUIInternal.ensureButtonContextMenu(child, this._toolbar, gPhotonStructure);
         CustomizableUIInternal.notifyListeners("onWidgetOverflow", child, this._target);
 
         this._list.insertBefore(child, this._list.firstChild);
         if (!this._toolbar.hasAttribute("overflowing")) {
           CustomizableUI.addListener(this);
         }
         this._toolbar.setAttribute("overflowing", "true");
       }
@@ -4311,16 +4323,17 @@ OverflowableToolbar.prototype = {
           break;
         }
       }
       if (!inserted) {
         this._target.appendChild(child);
       }
       child.removeAttribute("cui-anchorid");
       child.removeAttribute("overflowedItem");
+      CustomizableUIInternal.ensureButtonContextMenu(child, this._target);
       CustomizableUIInternal.notifyListeners("onWidgetUnderflow", child, this._target);
     }
 
     let win = this._target.ownerGlobal;
     win.UpdateUrlbarSearchSplitterState();
 
     if (!this._collapsed.size) {
       this._toolbar.removeAttribute("overflowing");
@@ -4390,31 +4403,33 @@ OverflowableToolbar.prototype = {
       if (nowOverflowed) {
         // NB: we're guaranteed that it has a previousSibling, because if it didn't,
         // we would have added it to the toolbar instead. See getOverflowedNextNode.
         let prevId = aNode.previousSibling.id;
         let minSize = this._collapsed.get(prevId);
         this._collapsed.set(aNode.id, minSize);
         aNode.setAttribute("cui-anchorid", this._chevron.id);
         aNode.setAttribute("overflowedItem", true);
+        CustomizableUIInternal.ensureButtonContextMenu(aNode, aContainer, gPhotonStructure);
         CustomizableUIInternal.notifyListeners("onWidgetOverflow", aNode, this._target);
       } else if (!nowInBar) {
         // If it is not overflowed and not in the toolbar, and was not overflowed
         // either, it moved out of the toolbar. That means there's now space in there!
         // Let's try to move stuff back:
         this._moveItemsBackToTheirOrigin(true);
       }
       // If it's in the toolbar now, then we don't care. An overflow event may
       // fire afterwards; that's ok!
     } else if (!nowOverflowed) {
       // If it used to be overflowed...
       // ... and isn't anymore, let's remove our bookkeeping:
       this._collapsed.delete(aNode.id);
       aNode.removeAttribute("cui-anchorid");
       aNode.removeAttribute("overflowedItem");
+      CustomizableUIInternal.ensureButtonContextMenu(aNode, aContainer);
       CustomizableUIInternal.notifyListeners("onWidgetUnderflow", aNode, this._target);
 
       if (!this._collapsed.size) {
         this._toolbar.removeAttribute("overflowing");
         CustomizableUI.removeListener(this);
       }
     } else if (aNode.previousSibling) {
       // but if it still is, it must have changed places. Bookkeep:
--- a/browser/components/customizableui/CustomizeMode.jsm
+++ b/browser/components/customizableui/CustomizeMode.jsm
@@ -284,16 +284,19 @@ CustomizeMode.prototype = {
 
       let panelHolder = document.getElementById("customization-panelHolder");
       let panelContainer = document.getElementById("customization-panel-container");
       let customizationContainer = document.getElementById("customization-container");
       let paletteContainer = document.getElementById("customization-palette-container");
       let contentContainer = document.getElementById("customization-content-container");
       let footer = document.getElementById("customization-footer");
       let doneButton = document.getElementById("customization-done-button");
+      let panelContextMenu = document.getElementById(kPanelItemContextMenu);
+      this._previousPanelContextMenuParent = panelContextMenu.parentNode;
+      document.getElementById("mainPopupSet").appendChild(panelContextMenu);
       if (gPhotonStructure) {
         if (!customizationContainer.hasAttribute("photon")) {
           contentContainer.appendChild(paletteContainer);
           contentContainer.appendChild(panelContainer);
           customizationContainer.appendChild(footer);
           customizationContainer.setAttribute("photon", "true");
           doneButton.hidden = false;
         }
@@ -570,16 +573,18 @@ CustomizeMode.prototype = {
 
         // We have to use setAttribute/removeAttribute here instead of the
         // property because the XBL property will be set later, and right
         // now we'd be setting an expando, which breaks the XBL property.
         document.getElementById("PanelUI-help").removeAttribute("disabled");
         document.getElementById("PanelUI-quit").removeAttribute("disabled");
         this.panelUIContents.removeAttribute("customize-transitioning");
       }
+      let panelContextMenu = document.getElementById(kPanelItemContextMenu);
+      this._previousPanelContextMenuParent.appendChild(panelContextMenu);
 
       // We need to set this._customizing to false before removing the tab
       // or the TabSelect event handler will think that we are exiting
       // customization mode for a second time.
       this._customizing = false;
 
       if (!gPhotonStructure) {
         let mainView = window.PanelUI.mainView;
@@ -2496,16 +2501,24 @@ CustomizeMode.prototype = {
   _findVisiblePreviousSiblingNode(aReferenceNode) {
     while (aReferenceNode &&
            aReferenceNode.localName == "toolbarpaletteitem" &&
            aReferenceNode.firstChild.hidden) {
       aReferenceNode = aReferenceNode.previousSibling;
     }
     return aReferenceNode;
   },
+
+  onPanelContextMenuShowing(event) {
+    let inPermanentArea = !gPhotonStructure ||
+                          !!event.target.triggerNode.closest("#widget-overflow-fixed-list");
+    let doc = event.target.ownerDocument;
+    doc.getElementById("customizationPanelItemContextMenuUnpin").hidden = !inPermanentArea;
+    doc.getElementById("customizationPanelItemContextMenuPin").hidden = inPermanentArea;
+  },
 };
 
 function __dumpDragData(aEvent, caller) {
   if (!gDebug) {
     return;
   }
   let str = "Dumping drag data (" + (caller ? caller + " in " : "") + "CustomizeMode.jsm) {\n";
   str += "  type: " + aEvent["type"] + "\n";
--- a/browser/components/customizableui/content/panelUI.inc.xul
+++ b/browser/components/customizableui/content/panelUI.inc.xul
@@ -354,16 +354,51 @@
           <label id="PanelUI-panic-warning">&panicButton.view.undoWarning;</label>
         </vbox>
         <button id="PanelUI-panic-view-button"
                 label="&panicButton.view.forgetButton;"/>
       </vbox>
     </panelview>
 
   </panelmultiview>
+
+  <!-- This menu is here because not having it in the menu in which it's used flickers
+       when hover styles overlap. See https://bugzilla.mozilla.org/show_bug.cgi?id=1378427 .
+       -->
+  <menupopup id="customizationPanelItemContextMenu"
+             onpopupshowing="gCustomizeMode.onPanelContextMenuShowing(event)">
+    <menuitem oncommand="gCustomizeMode.addToPanel(document.popupNode)"
+              id="customizationPanelItemContextMenuPin"
+              photonaccesskey="&customizeMenu.pinToOverflowMenu.accesskey;"
+              photonlabel="&customizeMenu.pinToOverflowMenu.label;"
+              accesskey="&customizeMenu.moveToPanel.accesskey;"
+              label="&customizeMenu.moveToPanel.label;"
+              closemenu="single"
+              class="customize-context-moveToPanel"/>
+    <menuitem oncommand="gCustomizeMode.addToToolbar(document.popupNode)"
+              id="customizationPanelItemContextMenuUnpin"
+              closemenu="single"
+              class="customize-context-moveToToolbar"
+              photonaccesskey="&customizeMenu.unpinFromOverflowMenu.accesskey;"
+              photonlabel="&customizeMenu.unpinFromOverflowMenu.label;"
+              accesskey="&customizeMenu.moveToToolbar.accesskey;"
+              label="&customizeMenu.moveToToolbar.label;"/>
+    <menuitem oncommand="gCustomizeMode.removeFromArea(document.popupNode)"
+              closemenu="single"
+              class="customize-context-removeFromPanel"
+              photonaccesskey="&customizeMenu.removeFromToolbar.accesskey;"
+              photonlabel="&customizeMenu.removeFromToolbar.label;"
+              accesskey="&customizeMenu.removeFromMenu.accesskey;"
+              label="&customizeMenu.removeFromMenu.label;"/>
+    <menuseparator/>
+    <menuitem command="cmd_CustomizeToolbars"
+              class="viewCustomizeToolbar"
+              accesskey="&viewCustomizeToolbar.accesskey;"
+              label="&viewCustomizeToolbar.label;"/>
+  </menupopup>
 </panel>
 
 <panel id="widget-overflow"
        role="group"
        type="arrow"
        noautofocus="true"
        position="bottomcenter topright"
 #ifndef MOZ_PHOTON_THEME
@@ -484,38 +519,16 @@
                      checkboxhidden="true"
                      hidden="true">
     <popupnotificationcontent id="update-restart-notification-content" orient="vertical">
       <description id="update-restart-description">&updateRestart.message;</description>
     </popupnotificationcontent>
   </popupnotification>
 </panel>
 
-<menupopup id="customizationPanelItemContextMenu">
-  <menuitem oncommand="gCustomizeMode.addToToolbar(document.popupNode)"
-            closemenu="single"
-            class="customize-context-moveToToolbar"
-            photonaccesskey="&customizeMenu.unpinFromOverflowMenu.accesskey;"
-            photonlabel="&customizeMenu.unpinFromOverflowMenu.label;"
-            accesskey="&customizeMenu.moveToToolbar.accesskey;"
-            label="&customizeMenu.moveToToolbar.label;"/>
-  <menuitem oncommand="gCustomizeMode.removeFromArea(document.popupNode)"
-            closemenu="single"
-            class="customize-context-removeFromPanel"
-            photonaccesskey="&customizeMenu.removeFromToolbar.accesskey;"
-            photonlabel="&customizeMenu.removeFromToolbar.label;"
-            accesskey="&customizeMenu.removeFromMenu.accesskey;"
-            label="&customizeMenu.removeFromMenu.label;"/>
-  <menuseparator/>
-  <menuitem command="cmd_CustomizeToolbars"
-            class="viewCustomizeToolbar"
-            accesskey="&viewCustomizeToolbar.accesskey;"
-            label="&viewCustomizeToolbar.label;"/>
-</menupopup>
-
 <menupopup id="customizationPaletteItemContextMenu">
   <menuitem oncommand="gCustomizeMode.addToToolbar(document.popupNode)"
             class="customize-context-addToToolbar"
             accesskey="&customizeMenu.addToToolbar.accesskey;"
             label="&customizeMenu.addToToolbar.label;"/>
   <menuitem oncommand="gCustomizeMode.addToPanel(document.popupNode)"
             class="customize-context-addToPanel"
             photonaccesskey="&customizeMenu.addToOverflowMenu.accesskey;"
--- a/browser/components/customizableui/test/browser_880164_customization_context_menus.js
+++ b/browser/components/customizableui/test/browser_880164_customization_context_menus.js
@@ -5,17 +5,17 @@
 "use strict";
 
 requestLongerTimeout(2);
 
 const isOSX = (Services.appinfo.OS === "Darwin");
 
 // Right-click on the home button should
 // show a context menu with options to move it.
-add_task(async function() {
+add_task(async function home_button_context() {
   await SpecialPowers.pushPrefEnv({set: [["browser.photon.structure.enabled", false]]});
   let contextMenu = document.getElementById("toolbar-context-menu");
   let shownPromise = popupShown(contextMenu);
   let homeButton = document.getElementById("home-button");
   EventUtils.synthesizeMouse(homeButton, 2, 2, {type: "contextmenu", button: 2 });
   await shownPromise;
 
   let expectedEntries = [
@@ -36,17 +36,17 @@ add_task(async function() {
   let hiddenPromise = popupHidden(contextMenu);
   contextMenu.hidePopup();
   await hiddenPromise;
 });
 
 // Right-click on an empty bit of tabstrip should
 // show a context menu without options to move it,
 // but with tab-specific options instead.
-add_task(async function() {
+add_task(async function tabstrip_context() {
   // ensure there are tabs to reload/bookmark:
   let extraTab = gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser);
   await promiseTabLoadEvent(extraTab, "http://example.com/");
   let contextMenu = document.getElementById("toolbar-context-menu");
   let shownPromise = popupShown(contextMenu);
   let tabstrip = document.getElementById("tabbrowser-tabs");
   let rect = tabstrip.getBoundingClientRect();
   EventUtils.synthesizeMouse(tabstrip, rect.width - 2, 2, {type: "contextmenu", button: 2 });
@@ -74,17 +74,17 @@ add_task(async function() {
   contextMenu.hidePopup();
   await hiddenPromise;
   gBrowser.removeTab(extraTab);
 });
 
 // Right-click on an empty bit of extra toolbar should
 // show a context menu with moving options disabled,
 // and a toggle option for the extra toolbar
-add_task(async function() {
+add_task(async function empty_toolbar_context() {
   let contextMenu = document.getElementById("toolbar-context-menu");
   let shownPromise = popupShown(contextMenu);
   let toolbar = createToolbarWithPlacements("880164_empty_toolbar", []);
   toolbar.setAttribute("context", "toolbar-context-menu");
   toolbar.setAttribute("toolbarname", "Fancy Toolbar for Context Menu");
   EventUtils.synthesizeMouseAtCenter(toolbar, {type: "contextmenu", button: 2 });
   await shownPromise;
 
@@ -108,17 +108,17 @@ add_task(async function() {
   contextMenu.hidePopup();
   await hiddenPromise;
   removeCustomToolbars();
 });
 
 
 // Right-click on the urlbar-container should
 // show a context menu with disabled options to move it.
-add_task(async function() {
+add_task(async function urlbar_context() {
   let contextMenu = document.getElementById("toolbar-context-menu");
   let shownPromise = popupShown(contextMenu);
   let urlBarContainer = document.getElementById("urlbar-container");
   // Need to make sure not to click within an edit field.
   EventUtils.synthesizeMouse(urlBarContainer, 100, 1, {type: "contextmenu", button: 2 });
   await shownPromise;
 
   let expectedEntries = [
@@ -138,17 +138,17 @@ add_task(async function() {
 
   let hiddenPromise = popupHidden(contextMenu);
   contextMenu.hidePopup();
   await hiddenPromise;
 });
 
 // Right-click on the searchbar and moving it to the menu
 // and back should move the search-container instead.
-add_task(async function() {
+add_task(async function searchbar_context_move_to_panel_and_back() {
   let searchbar = document.getElementById("searchbar");
   gCustomizeMode.addToPanel(searchbar);
   let placement = CustomizableUI.getPlacementOfWidget("search-container");
   is(placement.area, CustomizableUI.AREA_PANEL, "Should be in panel");
 
   let shownPanelPromise = promisePanelShown(window);
   PanelUI.toggle({type: "command"});
   await shownPanelPromise;
@@ -164,17 +164,17 @@ add_task(async function() {
   is(placement, null, "Should be in palette");
   CustomizableUI.reset();
   placement = CustomizableUI.getPlacementOfWidget("search-container");
   is(placement.area, CustomizableUI.AREA_NAVBAR, "Should be in navbar");
 });
 
 // Right-click on an item within the menu panel should
 // show a context menu with options to move it.
-add_task(async function() {
+add_task(async function context_within_panel() {
   let shownPanelPromise = promisePanelShown(window);
   PanelUI.toggle({type: "command"});
   await shownPanelPromise;
 
   let contextMenu = document.getElementById("customizationPanelItemContextMenu");
   let shownContextPromise = popupShown(contextMenu);
   let newWindowButton = document.getElementById("new-window-button");
   ok(newWindowButton, "new-window-button was found");
@@ -197,17 +197,17 @@ add_task(async function() {
 
   let hiddenPromise = promisePanelHidden(window);
   PanelUI.toggle({type: "command"});
   await hiddenPromise;
 });
 
 // Right-click on the home button while in customization mode
 // should show a context menu with options to move it.
-add_task(async function() {
+add_task(async function context_home_button_in_customize_mode() {
   await startCustomizing();
   let contextMenu = document.getElementById("toolbar-context-menu");
   let shownPromise = popupShown(contextMenu);
   let homeButton = document.getElementById("wrapper-home-button");
   EventUtils.synthesizeMouse(homeButton, 2, 2, {type: "contextmenu", button: 2});
   await shownPromise;
 
   let expectedEntries = [
@@ -227,17 +227,17 @@ add_task(async function() {
 
   let hiddenContextPromise = popupHidden(contextMenu);
   contextMenu.hidePopup();
   await hiddenContextPromise;
 });
 
 // Right-click on an item in the palette should
 // show a context menu with options to move it.
-add_task(async function() {
+add_task(async function context_click_in_palette() {
   let contextMenu = document.getElementById("customizationPaletteItemContextMenu");
   let shownPromise = popupShown(contextMenu);
   let openFileButton = document.getElementById("wrapper-open-file-button");
   EventUtils.synthesizeMouse(openFileButton, 2, 2, {type: "contextmenu", button: 2});
   await shownPromise;
 
   let expectedEntries = [
     [".customize-context-addToToolbar", true],
@@ -247,17 +247,17 @@ add_task(async function() {
 
   let hiddenContextPromise = popupHidden(contextMenu);
   contextMenu.hidePopup();
   await hiddenContextPromise;
 });
 
 // Right-click on an item in the panel while in customization mode
 // should show a context menu with options to move it.
-add_task(async function() {
+add_task(async function context_click_in_customize_mode() {
   let contextMenu = document.getElementById("customizationPanelItemContextMenu");
   let shownPromise = popupShown(contextMenu);
   let newWindowButton = document.getElementById("wrapper-new-window-button");
   EventUtils.synthesizeMouse(newWindowButton, 2, 2, {type: "contextmenu", button: 2});
   await shownPromise;
 
   let expectedEntries = [
     [".customize-context-moveToToolbar", true],
@@ -270,17 +270,17 @@ add_task(async function() {
   let hiddenContextPromise = popupHidden(contextMenu);
   contextMenu.hidePopup();
   await hiddenContextPromise;
   await endCustomizing();
 });
 
 // Test the toolbarbutton panel context menu in customization mode
 // without opening the panel before customization mode
-add_task(async function() {
+add_task(async function context_click_customize_mode_panel_not_opened() {
   this.otherWin = await openAndLoadWindow(null, true);
 
   await new Promise(resolve => waitForFocus(resolve, this.otherWin));
 
   await startCustomizing(this.otherWin);
 
   let contextMenu = this.otherWin.document.getElementById("customizationPanelItemContextMenu");
   let shownPromise = popupShown(contextMenu);
@@ -303,25 +303,26 @@ add_task(async function() {
   await promiseWindowClosed(this.otherWin);
   this.otherWin = null;
 
   await new Promise(resolve => waitForFocus(resolve, window));
 });
 
 // Bug 945191 - Combined buttons show wrong context menu options
 // when they are in the toolbar.
-add_task(async function() {
+add_task(async function context_combined_buttons_toolbar() {
   await startCustomizing();
   let contextMenu = document.getElementById("customizationPanelItemContextMenu");
   let shownPromise = popupShown(contextMenu);
   let zoomControls = document.getElementById("wrapper-zoom-controls");
   EventUtils.synthesizeMouse(zoomControls, 2, 2, {type: "contextmenu", button: 2});
   await shownPromise;
   // Execute the command to move the item from the panel to the toolbar.
-  contextMenu.childNodes[0].doCommand();
+  let moveToToolbar = contextMenu.querySelector("menuitem:not([hidden])");
+  moveToToolbar.doCommand();
   let hiddenPromise = popupHidden(contextMenu);
   contextMenu.hidePopup();
   await hiddenPromise;
   await endCustomizing();
 
   zoomControls = document.getElementById("zoom-controls");
   is(zoomControls.parentNode.id, "nav-bar-customization-target", "Zoom-controls should be on the nav-bar");
 
@@ -347,17 +348,17 @@ add_task(async function() {
 
   hiddenPromise = popupHidden(contextMenu);
   contextMenu.hidePopup();
   await hiddenPromise;
   await resetCustomization();
 });
 
 // Bug 947586 - After customization, panel items show wrong context menu options
-add_task(async function() {
+add_task(async function context_after_customization_panel() {
   await startCustomizing();
   await endCustomizing();
 
   await PanelUI.show();
 
   let contextMenu = document.getElementById("customizationPanelItemContextMenu");
   let shownContextPromise = popupShown(contextMenu);
   let newWindowButton = document.getElementById("new-window-button");
@@ -381,17 +382,17 @@ add_task(async function() {
 
   let hiddenPromise = promisePanelHidden(window);
   PanelUI.hide();
   await hiddenPromise;
 });
 
 
 // Bug 982027 - moving icon around removes custom context menu.
-add_task(async function() {
+add_task(async function custom_context_menus() {
   let widgetId = "custom-context-menu-toolbarbutton";
   let expectedContext = "myfancycontext";
   let widget = createDummyXULButton(widgetId, "Test ctxt menu");
   widget.setAttribute("context", expectedContext);
   CustomizableUI.addWidgetToArea(widgetId, CustomizableUI.AREA_NAVBAR);
   is(widget.getAttribute("context"), expectedContext, "Should have context menu when added to the toolbar.");
 
   await startCustomizing();
--- a/browser/components/customizableui/test/browser_photon_customization_context_menus.js
+++ b/browser/components/customizableui/test/browser_photon_customization_context_menus.js
@@ -8,17 +8,17 @@ requestLongerTimeout(2);
 
 const isOSX = (Services.appinfo.OS === "Darwin");
 
 const overflowButton = document.getElementById("nav-bar-overflow-button");
 const overflowPanel = document.getElementById("widget-overflow");
 
 // Right-click on the home button should
 // show a context menu with options to move it.
-add_task(async function() {
+add_task(async function home_button_context() {
   await SpecialPowers.pushPrefEnv({set: [["browser.photon.structure.enabled", true]]});
   let contextMenu = document.getElementById("toolbar-context-menu");
   let shownPromise = popupShown(contextMenu);
   let homeButton = document.getElementById("home-button");
   EventUtils.synthesizeMouse(homeButton, 2, 2, {type: "contextmenu", button: 2 });
   await shownPromise;
 
   let expectedEntries = [
@@ -39,17 +39,17 @@ add_task(async function() {
   let hiddenPromise = popupHidden(contextMenu);
   contextMenu.hidePopup();
   await hiddenPromise;
 });
 
 // Right-click on an empty bit of tabstrip should
 // show a context menu without options to move it,
 // but with tab-specific options instead.
-add_task(async function() {
+add_task(async function tabstrip_context() {
   // ensure there are tabs to reload/bookmark:
   let extraTab = gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser);
   await promiseTabLoadEvent(extraTab, "http://example.com/");
   let contextMenu = document.getElementById("toolbar-context-menu");
   let shownPromise = popupShown(contextMenu);
   let tabstrip = document.getElementById("tabbrowser-tabs");
   let rect = tabstrip.getBoundingClientRect();
   EventUtils.synthesizeMouse(tabstrip, rect.width - 2, 2, {type: "contextmenu", button: 2 });
@@ -77,17 +77,17 @@ add_task(async function() {
   contextMenu.hidePopup();
   await hiddenPromise;
   gBrowser.removeTab(extraTab);
 });
 
 // Right-click on an empty bit of extra toolbar should
 // show a context menu with moving options disabled,
 // and a toggle option for the extra toolbar
-add_task(async function() {
+add_task(async function empty_toolbar_context() {
   let contextMenu = document.getElementById("toolbar-context-menu");
   let shownPromise = popupShown(contextMenu);
   let toolbar = createToolbarWithPlacements("880164_empty_toolbar", []);
   toolbar.setAttribute("context", "toolbar-context-menu");
   toolbar.setAttribute("toolbarname", "Fancy Toolbar for Context Menu");
   EventUtils.synthesizeMouseAtCenter(toolbar, {type: "contextmenu", button: 2 });
   await shownPromise;
 
@@ -111,17 +111,17 @@ add_task(async function() {
   contextMenu.hidePopup();
   await hiddenPromise;
   removeCustomToolbars();
 });
 
 
 // Right-click on the urlbar-container should
 // show a context menu with disabled options to move it.
-add_task(async function() {
+add_task(async function urlbar_context() {
   let contextMenu = document.getElementById("toolbar-context-menu");
   let shownPromise = popupShown(contextMenu);
   let urlBarContainer = document.getElementById("urlbar-container");
   // Need to make sure not to click within an edit field.
   EventUtils.synthesizeMouse(urlBarContainer, 100, 1, {type: "contextmenu", button: 2 });
   await shownPromise;
 
   let expectedEntries = [
@@ -141,43 +141,43 @@ add_task(async function() {
 
   let hiddenPromise = popupHidden(contextMenu);
   contextMenu.hidePopup();
   await hiddenPromise;
 });
 
 // Right-click on the searchbar and moving it to the menu
 // and back should move the search-container instead.
-add_task(async function() {
+add_task(async function searchbar_context_move_to_panel_and_back() {
   let searchbar = document.getElementById("searchbar");
   gCustomizeMode.addToPanel(searchbar);
   let placement = CustomizableUI.getPlacementOfWidget("search-container");
   is(placement.area, CustomizableUI.AREA_FIXED_OVERFLOW_PANEL, "Should be in panel");
 
   let shownPanelPromise = popupShown(overflowPanel);
   overflowButton.click();
   await shownPanelPromise;
   let hiddenPanelPromise = popupHidden(overflowPanel);
-  overflowButton.click();
+  overflowPanel.hidePopup();
   await hiddenPanelPromise;
 
   gCustomizeMode.addToToolbar(searchbar);
   placement = CustomizableUI.getPlacementOfWidget("search-container");
   is(placement.area, CustomizableUI.AREA_NAVBAR, "Should be in navbar");
   gCustomizeMode.removeFromArea(searchbar);
   placement = CustomizableUI.getPlacementOfWidget("search-container");
   is(placement, null, "Should be in palette");
   CustomizableUI.reset();
   placement = CustomizableUI.getPlacementOfWidget("search-container");
   is(placement.area, CustomizableUI.AREA_NAVBAR, "Should be in navbar");
 });
 
 // Right-click on an item within the panel should
 // show a context menu with options to move it.
-add_task(async function() {
+add_task(async function context_within_panel() {
   CustomizableUI.addWidgetToArea("new-window-button", CustomizableUI.AREA_FIXED_OVERFLOW_PANEL);
   let shownPanelPromise = popupShown(overflowPanel);
   overflowButton.click();
   await shownPanelPromise;
 
   let contextMenu = document.getElementById("customizationPanelItemContextMenu");
   let shownContextPromise = popupShown(contextMenu);
   let newWindowButton = document.getElementById("new-window-button");
@@ -195,25 +195,25 @@ add_task(async function() {
   ];
   checkContextMenu(contextMenu, expectedEntries);
 
   let hiddenContextPromise = popupHidden(contextMenu);
   contextMenu.hidePopup();
   await hiddenContextPromise;
 
   let hiddenPromise = popupHidden(overflowPanel);
-  overflowButton.click();
+  overflowPanel.hidePopup();
   await hiddenPromise;
 
   CustomizableUI.removeWidgetFromArea("new-window-button");
 });
 
 // Right-click on the home button while in customization mode
 // should show a context menu with options to move it.
-add_task(async function() {
+add_task(async function context_home_button_in_customize_mode() {
   await startCustomizing();
   let contextMenu = document.getElementById("toolbar-context-menu");
   let shownPromise = popupShown(contextMenu);
   let homeButton = document.getElementById("wrapper-home-button");
   EventUtils.synthesizeMouse(homeButton, 2, 2, {type: "contextmenu", button: 2});
   await shownPromise;
 
   let expectedEntries = [
@@ -233,17 +233,17 @@ add_task(async function() {
 
   let hiddenContextPromise = popupHidden(contextMenu);
   contextMenu.hidePopup();
   await hiddenContextPromise;
 });
 
 // Right-click on an item in the palette should
 // show a context menu with options to move it.
-add_task(async function() {
+add_task(async function context_click_in_palette() {
   let contextMenu = document.getElementById("customizationPaletteItemContextMenu");
   let shownPromise = popupShown(contextMenu);
   let openFileButton = document.getElementById("wrapper-open-file-button");
   EventUtils.synthesizeMouse(openFileButton, 2, 2, {type: "contextmenu", button: 2});
   await shownPromise;
 
   let expectedEntries = [
     [".customize-context-addToToolbar", true],
@@ -253,17 +253,17 @@ add_task(async function() {
 
   let hiddenContextPromise = popupHidden(contextMenu);
   contextMenu.hidePopup();
   await hiddenContextPromise;
 });
 
 // Right-click on an item in the panel while in customization mode
 // should show a context menu with options to move it.
-add_task(async function() {
+add_task(async function context_click_in_customize_mode() {
   CustomizableUI.addWidgetToArea("new-window-button", CustomizableUI.AREA_FIXED_OVERFLOW_PANEL);
   let contextMenu = document.getElementById("customizationPanelItemContextMenu");
   let shownPromise = popupShown(contextMenu);
   let newWindowButton = document.getElementById("wrapper-new-window-button");
   EventUtils.synthesizeMouse(newWindowButton, 2, 2, {type: "contextmenu", button: 2});
   await shownPromise;
 
   let expectedEntries = [
@@ -278,17 +278,17 @@ add_task(async function() {
   contextMenu.hidePopup();
   await hiddenContextPromise;
   CustomizableUI.removeWidgetFromArea("new-window-button");
   await endCustomizing();
 });
 
 // Test the toolbarbutton panel context menu in customization mode
 // without opening the panel before customization mode
-add_task(async function() {
+add_task(async function context_click_customize_mode_panel_not_opened() {
   CustomizableUI.addWidgetToArea("new-window-button", CustomizableUI.AREA_FIXED_OVERFLOW_PANEL);
   this.otherWin = await openAndLoadWindow(null, true);
 
   await new Promise(resolve => waitForFocus(resolve, this.otherWin));
 
   await startCustomizing(this.otherWin);
 
   let contextMenu = this.otherWin.document.getElementById("customizationPanelItemContextMenu");
@@ -313,26 +313,27 @@ add_task(async function() {
   await promiseWindowClosed(this.otherWin);
   this.otherWin = null;
 
   await new Promise(resolve => waitForFocus(resolve, window));
 });
 
 // Bug 945191 - Combined buttons show wrong context menu options
 // when they are in the toolbar.
-add_task(async function() {
+add_task(async function context_combined_buttons_toolbar() {
   CustomizableUI.addWidgetToArea("zoom-controls", CustomizableUI.AREA_FIXED_OVERFLOW_PANEL);
   await startCustomizing();
   let contextMenu = document.getElementById("customizationPanelItemContextMenu");
   let shownPromise = popupShown(contextMenu);
   let zoomControls = document.getElementById("wrapper-zoom-controls");
   EventUtils.synthesizeMouse(zoomControls, 2, 2, {type: "contextmenu", button: 2});
   await shownPromise;
   // Execute the command to move the item from the panel to the toolbar.
-  contextMenu.childNodes[0].doCommand();
+  let moveToToolbar = contextMenu.querySelector("menuitem:not([hidden])");
+  moveToToolbar.doCommand();
   let hiddenPromise = popupHidden(contextMenu);
   contextMenu.hidePopup();
   await hiddenPromise;
   await endCustomizing();
 
   zoomControls = document.getElementById("zoom-controls");
   is(zoomControls.parentNode.id, "nav-bar-customization-target", "Zoom-controls should be on the nav-bar");
 
@@ -358,17 +359,17 @@ add_task(async function() {
 
   hiddenPromise = popupHidden(contextMenu);
   contextMenu.hidePopup();
   await hiddenPromise;
   await resetCustomization();
 });
 
 // Bug 947586 - After customization, panel items show wrong context menu options
-add_task(async function() {
+add_task(async function context_after_customization_panel() {
   info("Check panel context menu is correct after customization");
   await startCustomizing();
   await endCustomizing();
 
   CustomizableUI.addWidgetToArea("new-window-button", CustomizableUI.AREA_FIXED_OVERFLOW_PANEL);
   let shownPanelPromise = popupShown(overflowPanel);
   overflowButton.click();
   await shownPanelPromise;
@@ -390,24 +391,24 @@ add_task(async function() {
   ];
   checkContextMenu(contextMenu, expectedEntries);
 
   let hiddenContextPromise = popupHidden(contextMenu);
   contextMenu.hidePopup();
   await hiddenContextPromise;
 
   let hiddenPromise = popupHidden(overflowPanel);
-  overflowButton.click();
+  overflowPanel.hidePopup();
   await hiddenPromise;
   CustomizableUI.removeWidgetFromArea("new-window-button");
 });
 
 
 // Bug 982027 - moving icon around removes custom context menu.
-add_task(async function() {
+add_task(async function custom_context_menus() {
   let widgetId = "custom-context-menu-toolbarbutton";
   let expectedContext = "myfancycontext";
   let widget = createDummyXULButton(widgetId, "Test ctxt menu");
   widget.setAttribute("context", expectedContext);
   CustomizableUI.addWidgetToArea(widgetId, CustomizableUI.AREA_NAVBAR);
   is(widget.getAttribute("context"), expectedContext, "Should have context menu when added to the toolbar.");
 
   await startCustomizing();