Bug 1378427 - move context menus around, fix flickering in dynamic portion of the overflow menu for photon, r=jaws
authorGijs Kruitbosch <gijskruitbosch@gmail.com>
Fri, 07 Jul 2017 15:54:13 +0100
changeset 368211 13302a007a78bc3060bffbdf7a29a7c14f25fa46
parent 368210 705e581e56eb71a33b98ea10c3d680f982fd9ad0
child 368239 3c1871f07fbe11280460232b55f78cf4f5e54d2a
push id46245
push usergijskruitbosch@gmail.com
push dateTue, 11 Jul 2017 10:05:25 +0000
treeherderautoland@13302a007a78 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjaws
bugs1378427, 1354078
milestone56.0a1
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
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(".customize-context-moveToToolbar");
+  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(".customize-context-moveToToolbar");
+  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();