Bug 1521016 - remove threadPaneColumnPicker and instead use customzied built-in thread-pane-treecols and thread-pane-treecolpicker for the purpose. r=arshad a=jorgk
authorMagnus Melin <mkmelin+mozilla@iki.fi>
Fri, 08 Feb 2019 11:30:56 +0100
changeset 33474 86cb9d0c8982
parent 33473 fe791ff3dc62
child 33475 2d307b1bc4a3
push id2371
push usermozilla@jorgk.com
push dateFri, 08 Feb 2019 10:35:50 +0000
treeherdercomm-beta@86cb9d0c8982 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersarshad, jorgk
bugs1521016
Bug 1521016 - remove threadPaneColumnPicker and instead use customzied built-in thread-pane-treecols and thread-pane-treecolpicker for the purpose. r=arshad a=jorgk
mail/base/content/mailContextMenus.js
mail/base/content/mailWidgets.js
mail/base/content/messenger.xul
mail/base/content/tabmail.css
mail/base/content/threadPaneColumnPicker.xml
mail/base/jar.mn
mail/locales/en-US/chrome/messenger/messenger.dtd
mail/test/mozmill/folder-display/test-columns.js
mail/test/mozmill/folder-display/test-right-click-middle-click-messages.js
mail/test/mozmill/shared-modules/test-window-helpers.js
--- a/mail/base/content/mailContextMenus.js
+++ b/mail/base/content/mailContextMenus.js
@@ -54,16 +54,25 @@ function mailContextOnPopupHiding(aEvent
 
   let wasInThreadPane = gContextMenu.inThreadPane;
   gContextMenu = null;
   if (wasInThreadPane)
     RestoreSelectionWithoutContentLoad(GetThreadTree());
 }
 
 function fillMailContextMenu(event) {
+  let target = document.popupNode;
+  if (target.localName == "treecol") {
+    let treeColPicker = target.parentNode.querySelector("treecolpicker");
+    let popup = treeColPicker.querySelector(`menupopup[anonid="popup"]`);
+    treeColPicker.buildPopup(popup);
+    popup.openPopup(target, "after_start", 0, 0, true);
+    return false;
+  }
+
   // If the popupshowing was for a submenu, we don't need to do anything.
   if (event.target != event.currentTarget)
     return true;
 
   // No menu on grouped header row currently, any command would be an implied
   // multiselect.
   if (gFolderDisplay.tree) {
     let row = gFolderDisplay.tree.getRowAt(event.clientX, event.clientY);
@@ -283,23 +292,20 @@ function folderPaneOnPopupHiding() {
   RestoreSelectionWithoutContentLoad(document.getElementById("folderTree"));
 }
 
 /* eslint-disable complexity */
 function fillFolderPaneContextMenu(aEvent) {
   let target = document.popupNode;
   // If a column header was clicked, show the column picker.
   if (target.localName == "treecol") {
-    let treecols = target.parentNode;
-    let treeColPicker = treecols.querySelector("treecolpicker");
-    if (treeColPicker) {
-      let popup = document.getAnonymousElementByAttribute(treeColPicker, "anonid", "popup");
-      treeColPicker.buildPopup(popup);
-      popup.openPopup(target, "after_start", 0, 0, true);
-    }
+    let treeColPicker = target.parentNode.querySelector("treecolpicker");
+    let popup = treeColPicker.querySelector(`menupopup[anonid="popup"]`);
+    treeColPicker.buildPopup(popup);
+    popup.openPopup(target, "after_start", 0, 0, true);
     return false;
   }
 
   // Do not show menu if rows are selected.
   var bundle = document.getElementById("bundle_messenger");
   var folders = gFolderTreeView.getSelectedFolders();
   if (!folders.length)
     return false;
--- a/mail/base/content/mailWidgets.js
+++ b/mail/base/content/mailWidgets.js
@@ -3,16 +3,22 @@
  * 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/. */
 
 /* global MozXULElement */
 /* global openUILink */
 /* global MessageIdClick */
 /* global onClickEmailStar */
 /* global onClickEmailPresence */
+/* global gFolderDisplay */
+
+ChromeUtils.import("resource://gre/modules/Services.jsm");
+ChromeUtils.import("resource:///modules/MailUtils.jsm");
+ChromeUtils.import("resource:///modules/MailServices.jsm");
+ChromeUtils.import("resource:///modules/DBViewWrapper.jsm");
 
 class MozMailHeaderfield extends MozXULElement {
   connectedCallback() {
     this.setAttribute("context", "copyPopup");
     this.classList.add("headerValue");
   }
 
   set headerValue(val) {
@@ -31,17 +37,16 @@ class MozMailUrlfield extends MozMailHea
       }
     });
   }
 }
 
 class MozMailHeaderfieldTags extends MozXULElement {
   connectedCallback() {
     this.classList.add("headerValue");
-    ChromeUtils.import("resource:///modules/MailServices.jsm");
   }
 
   set headerValue(val) {
     return this.buildTags(val);
   }
 
   buildTags(tags) {
     // tags contains a list of actual tag names (not the keys), delimited by spaces
@@ -293,18 +298,188 @@ class MozTreecolImage extends customElem
 
     if (src != null) {
       this.image.setAttribute("src", src);
     } else {
       this.image.removeAttribute("src");
     }
   }
 }
+customElements.define("treecol-image", MozTreecolImage, { extends: "treecol" });
+
+/**
+ * Class extending treecols. This features a customized treecolpicker that
+ * features a menupopup with more items than the standard one.
+ * @augments {MozTreecols}
+ */
+class MozThreadPaneTreecols extends customElements.get("treecols") {
+  connectedCallback() {
+    if (this.delayConnectedCallback()) {
+      return;
+    }
+    let treecolpicker = this.querySelector("treecolpicker:not([is]");
+
+    // Can't change the super treecolpicker by setting
+    // is="thread-pane-treecolpicker" since that needs to be there at the
+    // parsing stage to take effect.
+    // So, remove the existing treecolpicker, and add a new one.
+    if (treecolpicker) {
+      treecolpicker.remove();
+    }
+    if (!this.querySelector("treecolpicker[is=thread-pane-treecolpicker]")) {
+      this.appendChild(MozXULElement.parseXULToFragment(`
+        <treecolpicker is="thread-pane-treecolpicker" class="treecol-image" fixed="true"></treecolpicker>
+      `));
+    }
+    // Exceptionally apply super late, so we get the other goodness from there
+    // now that the treecolpicker is corrected.
+    super.connectedCallback();
+  }
+}
+customElements.define("thread-pane-treecols", MozThreadPaneTreecols, { extends: "treecols" });
+
+/**
+ * Class extending treecolpicker. This implements UI to apply column settings
+ * of the current thread pane to other mail folders too.
+ * @augments {MozTreecolPicker}
+ */
+class MozThreadPaneTreeColpicker extends customElements.get("treecolpicker") {
+  connectedCallback() {
+    super.connectedCallback();
+    if (this.delayConnectedCallback()) {
+      return;
+    }
+    let popup = this.querySelector(`menupopup[anonid="popup"]`);
+
+    // We'll add an "Apply columns to..." menu
+    popup.appendChild(MozXULElement.parseXULToFragment(`
+      <menu class="applyTo-menu" label="&columnPicker.applyTo.label;">
+        <menupopup>
+          <menu class="applyToFolder-menu" label="&columnPicker.applyToFolder.label;">
+            <menupopup class="applyToFolder" type="folder" showFileHereLabel="true" position="start_before"></menupopup>
+          </menu>
+          <menu class="applyToFolderAndChildren-menu" label="&columnPicker.applyToFolderAndChildren.label;">
+            <menupopup class="applyToFolderAndChildren" type="folder" showFileHereLabel="true" showAccountsFileHere="true" position="start_before"></menupopup>
+          </menu>
+        </menupopup>
+      </menu>
+    `, ["chrome://messenger/locale/messenger.dtd"]));
+
+    let confirmApply = (destFolder, useChildren) => {
+      // Confirm the action with the user.
+      let bundle = document.getElementById("bundle_messenger");
+      let title = (useChildren) ?
+        "threadPane.columnPicker.confirmFolder.withChildren.title" :
+        "threadPane.columnPicker.confirmFolder.noChildren.title";
+      let confirmed = Services.prompt.confirm(null, title,
+        bundle.getFormattedString(title, [destFolder.prettyName]));
+      if (confirmed) {
+        this._applyColumns(destFolder, useChildren);
+      }
+    };
+
+    let applyToFolderMenu = this.querySelector(".applyToFolder-menu");
+    applyToFolderMenu.addEventListener("command", (event) => {
+      confirmApply(event.originalTarget._folder, false);
+    });
+
+    let applyToFolderAndChildrenMenu = this.querySelector(".applyToFolderAndChildren-menu");
+    applyToFolderAndChildrenMenu.addEventListener("command", (event) => {
+      confirmApply(event.originalTarget._folder, true);
+    });
+  }
+
+  // XXX: this shouldn't need to be overridden. ATM, the removal of children
+  // while aPopup.childNodes.length > 2 is forcing us. We have three since we
+  // add one menu.
+  /** @override */
+  buildPopup(aPopup) {
+    // We no longer cache the picker content, remove the old content related to
+    // the cols - menuitem and separator should stay.
+    this.querySelectorAll("[colindex]").forEach((e) => { e.remove(); });
+
+    var refChild = aPopup.firstChild;
+
+    var tree = this.parentNode.parentNode;
+    for (var currCol = tree.columns.getFirstColumn(); currCol; currCol = currCol.getNext()) {
+      // Construct an entry for each column in the row, unless
+      // it is not being shown.
+      var currElement = currCol.element;
+      if (!currElement.hasAttribute("ignoreincolumnpicker")) {
+        var popupChild = document.createElement("menuitem");
+        popupChild.setAttribute("type", "checkbox");
+        var columnName = currElement.getAttribute("display") ||
+          currElement.getAttribute("label");
+        popupChild.setAttribute("label", columnName);
+        popupChild.setAttribute("colindex", currCol.index);
+        if (currElement.getAttribute("hidden") != "true")
+          popupChild.setAttribute("checked", "true");
+        if (currCol.primary)
+          popupChild.setAttribute("disabled", "true");
+        aPopup.insertBefore(popupChild, refChild);
+      }
+    }
+
+    var hidden = !tree.enableColumnDrag;
+    this.querySelectorAll(":not([colindex])").forEach((e) => { e.hidden = hidden; });
+  }
+
+  _applyColumns(destFolder, useChildren) {
+    // Get the current folder's column state, plus the "swapped" column
+    // state, which swaps "From" and "Recipient" if only one is shown.
+    // This is useful for copying an incoming folder's columns to an
+    // outgoing folder, or vice versa.
+    let colState = gFolderDisplay.getColumnStates();
+
+    let myColStateString = JSON.stringify(colState);
+    let swappedColStateString;
+    if (colState.senderCol.visible != colState.recipientCol.visible) {
+      let tmp = colState.senderCol;
+      colState.senderCol = colState.recipientCol;
+      colState.recipientCol = tmp;
+      swappedColStateString = JSON.stringify(colState);
+    } else {
+      swappedColStateString = myColStateString;
+    }
+
+    let isOutgoing = function(folder) {
+      return folder.isSpecialFolder(
+        DBViewWrapper.prototype.OUTGOING_FOLDER_FLAGS, true
+      );
+    };
+
+    let amIOutgoing = isOutgoing(gFolderDisplay.displayedFolder);
+
+    let colStateString = function(folder) {
+      return (isOutgoing(folder) == amIOutgoing ? myColStateString :
+        swappedColStateString);
+    };
+
+    // Now propagate appropriately...
+    const propName = gFolderDisplay.PERSISTED_COLUMN_PROPERTY_NAME;
+    if (useChildren) {
+      // Generate an observer notification when we have finished
+      // configuring all folders.  This is currently done for the benefit
+      // of our mozmill tests.
+      let observerCallback = function() {
+        Services.obs.notifyObservers(gFolderDisplay.displayedFolder,
+          "msg-folder-columns-propagated");
+      };
+      MailUtils.setStringPropertyOnFolderAndDescendents(
+        propName, colStateString, destFolder, observerCallback
+      );
+    } else {
+      destFolder.setStringProperty(propName, colStateString(destFolder));
+      // null out to avoid memory bloat
+      destFolder.msgDatabase = null;
+    }
+  }
+}
+customElements.define("thread-pane-treecolpicker", MozThreadPaneTreeColpicker, { extends: "treecolpicker" });
 
 customElements.define("mail-headerfield", MozMailHeaderfield);
 customElements.define("mail-urlfield", MozMailUrlfield);
 customElements.define("mail-tagfield", MozMailHeaderfieldTags);
 customElements.define("mail-newsgroup", MozMailNewsgroup);
 customElements.define("mail-newsgroups-headerfield", MozMailNewsgroupsHeaderfield);
 customElements.define("mail-messageid", MozMailMessageid);
 customElements.define("mail-emailaddress", MozMailEmailaddress);
 customElements.define("mail-emailheaderfield", MozMailEmailheaderfield);
-customElements.define("treecol-image", MozTreecolImage, { extends: "treecol" });
--- a/mail/base/content/messenger.xul
+++ b/mail/base/content/messenger.xul
@@ -553,17 +553,17 @@
                           class="plain"
                           lastfoldersent="false"
                           keepcurrentinview="true"
                           disableKeyNavigation="true"
                           context="mailContext"
                           onkeydown="ThreadPaneKeyDown(event);"
                           onselect="ThreadPaneSelectionChanged();"
                           >
-                      <treecols id="threadCols" pickertooltiptext="&columnChooser2.tooltip;">
+                      <treecols id="threadCols" is="thread-pane-treecols" pickertooltiptext="&columnChooser2.tooltip;">
                         <treecol is="treecol-image" id="threadCol" fixed="true" cycler="true"
                                  class="treecol-image threadColumnHeader" currentView="unthreaded"
                                  label="&threadColumn.label;" tooltiptext="&threadColumn2.tooltip;"/>
                         <splitter class="tree-splitter"/>
                         <treecol is="treecol-image" id="flaggedCol" fixed="true" cycler="true"
                                  class="treecol-image flagColumnHeader"
                                  label="&starredColumn.label;" tooltiptext="&starredColumn2.tooltip;"/>
                         <splitter class="tree-splitter"/>
--- a/mail/base/content/tabmail.css
+++ b/mail/base/content/tabmail.css
@@ -67,17 +67,8 @@
 }
 
 .tab-throbber:not([busy]):not([thinking]),
 .tab-throbber[busy] + .tab-icon-image,
 .tab-throbber[thinking] + .tab-icon-image,
 .tab-throbber[busy][thinking] + .tab-icon-image {
   display: none;
 }
-
-/**
- * Override the thread pane column picker.
- * We do it here because we don't want it in the Search dialog.
- */
-
-#threadCols > treecolpicker {
-  -moz-binding: url("chrome://messenger/content/threadPaneColumnPicker.xml#threadPaneColumnPicker");
-}
deleted file mode 100644
--- a/mail/base/content/threadPaneColumnPicker.xml
+++ /dev/null
@@ -1,243 +0,0 @@
-<?xml version="1.0"?>
-<!-- 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/. -->
-
-<!-- import-globals-from folderDisplay.js -->
-<!-- import-globals-from mailWindow.js -->
-
-<!DOCTYPE window [
-<!ENTITY % messengerDTD SYSTEM "chrome://messenger/locale/messenger.dtd" >
-%messengerDTD;
-]>
-
-<bindings id="threadPaneColumnPickerBindings"
-          xmlns="http://www.mozilla.org/xbl"
-          xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-          xmlns:xbl="http://www.mozilla.org/xbl">
-
-  <!--
-    - Because the columnpicker is implicitly created by the treecols binding
-    - and it does not pass anything in, we are compelled to override the binding
-    - (via CSS rules in messenger.css) in order to add custom menu options to
-    - the list.
-    -
-    - This is now a cut-paste-modify of the original tree.xml#columnpicker
-    - since we had to override everything save for the accessibleType anyways.
-    -->
-  <binding id="threadPaneColumnPicker" display="xul:button" role="xul:button"
-           extends="chrome://global/content/bindings/general.xml#basecontrol">
-    <content>
-      <xul:image class="tree-columnpicker-icon"/>
-      <xul:menupopup anonid="popup">
-        <xul:menuseparator anonid="menuseparator"/>
-        <xul:menuitem anonid="reset" label="&columnPicker.resetToInbox.label;"/>
-        <xul:menu anonid="applyTo-menu"
-                  label="&columnPicker.applyTo.label;">
-          <xul:menupopup>
-            <xul:menu anonid="applyToFolder-menu"
-                      label="&columnPicker.applyToFolder.label;">
-              <xul:menupopup anonid="applyToFolder"
-                             type="folder"
-                             showFileHereLabel="true"
-                             position="start_before"
-                             />
-            </xul:menu>
-            <xul:menu anonid="applyToFolderAndChildren-menu"
-                      label="&columnPicker.applyToFolderAndChildren.label;">
-              <xul:menupopup anonid="applyToFolderAndChildren"
-                             type="folder"
-                             showFileHereLabel="true"
-                             showAccountsFileHere="true"
-                             position="start_before"/>
-            </xul:menu>
-          </xul:menupopup>
-        </xul:menu>
-      </xul:menupopup>
-    </content>
-
-    <implementation>
-      <method name="buildPopup">
-        <parameter name="aPopup"/>
-        <body><![CDATA[
-          while (aPopup.childNodes.length > 3)
-            aPopup.firstChild.remove();
-
-          let refChild = aPopup.firstChild;
-
-          let tree = this.parentNode.parentNode;
-          for (let currCol = tree.columns.getFirstColumn(); currCol;
-               currCol = currCol.getNext()) {
-            // Construct an entry for each column in the row, unless
-            // it is not being shown.
-            let currElement = currCol.element;
-            if (!currElement.hasAttribute("ignoreincolumnpicker")) {
-              let popupChild = document.createElement("menuitem");
-              popupChild.setAttribute("type", "checkbox");
-              let columnName = currElement.getAttribute("display") ||
-                               currElement.getAttribute("label");
-              popupChild.setAttribute("label", columnName);
-              popupChild.setAttribute("colindex", currCol.index);
-              if (currElement.getAttribute("hidden") != "true")
-                popupChild.setAttribute("checked", "true");
-              if (currCol.primary)
-                popupChild.setAttribute("disabled", "true");
-              aPopup.insertBefore(popupChild, refChild);
-            }
-          }
-        ]]></body>
-      </method>
-
-      <method name="_showPopup">
-        <body><![CDATA[
-          let popup = document.getAnonymousElementByAttribute(
-            this, "anonid", "popup"
-          );
-          this.buildPopup(popup);
-          popup.openPopup(this, "after_end");
-        ]]></body>
-      </method>
-
-      <method name="_toggleColumn">
-        <parameter name="aColIndex"/>
-        <body><![CDATA[
-          let tree = this.parentNode.parentNode;
-          let column = tree.columns[aColIndex];
-          if (column) {
-            let element = column.element;
-            if (element.getAttribute("hidden") == "true")
-              element.setAttribute("hidden", "false");
-            else
-              element.setAttribute("hidden", "true");
-          }
-        ]]></body>
-      </method>
-
-      <method name="_resetColumns">
-        <body><![CDATA[
-          let columnStates =
-            gFolderDisplay._getDefaultColumnsForCurrentFolder();
-          gFolderDisplay.setColumnStates(columnStates, true);
-        ]]></body>
-      </method>
-
-      <method name="_useChildren">
-        <parameter name="aTarget"/>
-        <body><![CDATA[
-          // Let's figure out which of the actions they chose by walking the
-          // parent chain until we find one of them.
-          let noChildrenPopup = document.getAnonymousElementByAttribute(
-            this, "anonid", "applyToFolder"
-          );
-          let yesChildrenPopup = document.getAnonymousElementByAttribute(
-            this, "anonid", "applyToFolderAndChildren"
-          );
-
-          let parent = aTarget.parentNode;
-          while (parent != noChildrenPopup && parent != yesChildrenPopup) {
-            parent = parent.parentNode;
-          }
-          return parent == yesChildrenPopup;
-        ]]></body>
-      </method>
-
-      <method name="_applyColumns">
-        <parameter name="aDestFolder"/>
-        <parameter name="aUseChildren"/>
-        <body><![CDATA[
-          // Get the current folder's column state, plus the "swapped" column
-          // state, which swaps "From" and "Recipient" if only one is shown.
-          // This is useful for copying an incoming folder's columns to an
-          // outgoing folder, or vice versa.
-          let colState = gFolderDisplay.getColumnStates();
-
-          let myColStateString = JSON.stringify(colState);
-          let swappedColStateString;
-          if (colState.senderCol.visible != colState.recipientCol.visible) {
-            let tmp = colState.senderCol;
-            colState.senderCol = colState.recipientCol;
-            colState.recipientCol = tmp;
-            swappedColStateString = JSON.stringify(colState);
-          } else {
-            swappedColStateString = myColStateString;
-          }
-
-          function isOutgoing(folder) {
-            return folder.isSpecialFolder(
-              DBViewWrapper.prototype.OUTGOING_FOLDER_FLAGS, true
-            );
-          }
-
-          let amIOutgoing = isOutgoing(gFolderDisplay.displayedFolder);
-          function colStateString(folder) {
-            return (isOutgoing(folder) == amIOutgoing ? myColStateString :
-                    swappedColStateString);
-          }
-
-          // Now propagate appropriately...
-          const propName = gFolderDisplay.PERSISTED_COLUMN_PROPERTY_NAME;
-          if (aUseChildren) {
-            // Generate an observer notification when we have finished
-            // configuring all folders.  This is currently done for the benefit
-            // of our mozmill tests.
-            let observerCallback = function() {
-              Services.obs.notifyObservers(gFolderDisplay.displayedFolder,
-                                           "msg-folder-columns-propagated");
-            };
-            MailUtils.setStringPropertyOnFolderAndDescendents(
-              propName, colStateString, aDestFolder, observerCallback
-            );
-          } else {
-            aDestFolder.setStringProperty(propName,
-                                          colStateString(aDestFolder));
-            // null out to avoid memory bloat
-            aDestFolder.msgDatabase = null;
-          }
-        ]]></body>
-      </method>
-    </implementation>
-    <handlers>
-      <handler event="command"><![CDATA[
-        ChromeUtils.import("resource://gre/modules/Services.jsm");
-
-        // Are they clicking on our header to get us to show the column list?
-        if (event.originalTarget == this) {
-          this._showPopup();
-          return;
-        }
-
-        // Are they clicking on one of the columns in the list?
-        if (event.originalTarget.hasAttribute("colindex")) {
-          this._toggleColumn(event.originalTarget.getAttribute("colindex"));
-          return;
-        }
-
-        // Did they click the reset button?
-        let resetMenu = document.getAnonymousElementByAttribute(
-                          this, "anonid", "reset");
-        if (event.originalTarget == resetMenu) {
-          this._resetColumns();
-          return;
-        }
-
-        // Otherwise an exciting action has occurred!
-        let destFolder = event.originalTarget._folder;
-        let useChildren = this._useChildren(event.originalTarget);
-
-        // Confirm the action with the user.
-        let bundle = document.getElementById("bundle_messenger");
-        let stringBase = "threadPane.columnPicker.confirmFolder." +
-          (useChildren ? "withChildren." : "noChildren.");
-        let confirmed = Services.prompt.confirm(null,
-          bundle.getString(stringBase + "title"),
-          bundle.getFormattedString(stringBase + "message",
-                                    [destFolder.prettyName]));
-        if (!confirmed)
-          return;
-
-        this._applyColumns(destFolder, useChildren);
-      ]]></handler>
-    </handlers>
-  </binding>
-
-</bindings>
--- a/mail/base/jar.mn
+++ b/mail/base/jar.mn
@@ -81,17 +81,16 @@ messenger.jar:
     content/messenger/search.xml                    (content/search.xml)
     content/messenger/tabmail.xml                   (content/tabmail.xml)
     content/messenger/tabmail.css                   (content/tabmail.css)
     content/messenger/statuspanel.js                (content/statuspanel.js)
     content/messenger/newTagDialog.xul              (content/newTagDialog.xul)
     content/messenger/newTagDialog.js               (content/newTagDialog.js)
     content/messenger/composerOverlay.css           (content/composerOverlay.css)
     content/messenger/threadPane.js                 (content/threadPane.js)
-    content/messenger/threadPaneColumnPicker.xml    (content/threadPaneColumnPicker.xml)
     content/messenger/protovis-r2.6-modded.js       (content/protovis-r2.6-modded.js)
     content/messenger/dark.icon.svg                 (content/dark.icon.svg)
     content/messenger/light.icon.svg                (content/light.icon.svg)
 #ifdef XP_MACOSX
     content/messenger/macMessengerMenu.js           (content/macMessengerMenu.js)
 #endif
     content/messenger/selectionsummaries.js         (content/selectionsummaries.js)
     content/messenger/multimessageview.css          (content/multimessageview.css)
--- a/mail/locales/en-US/chrome/messenger/messenger.dtd
+++ b/mail/locales/en-US/chrome/messenger/messenger.dtd
@@ -808,22 +808,16 @@
 <!ENTITY contextWatchThreadMenu.accesskey "">
 <!ENTITY contextSaveAs.label "Save As…">
 <!ENTITY contextSaveAs.accesskey "S">
 <!ENTITY contextPrint.label "Print…">
 <!ENTITY contextPrint.accesskey "P">
 <!ENTITY contextPrintPreview.label "Print Preview">
 <!ENTITY contextPrintPreview.accesskey "v">
 
-<!-- Thread Pane Column Picker -->
-<!-- LOCALIZATION NOTE (columnPicker.resetToInbox.label):
-     This option in the thread pane column picker causes us to reset the
-     customizations for the thread pane columns in this folder to their default.
-  -->
-<!ENTITY columnPicker.resetToInbox.label "Reset columns to default">
 <!-- LOCALIZATION NOTE (columnPicker.applyTo.label):
      This option in the thread pane column picker pops up a sub-menu containing
      the "columnPicker.applyToFolder.label" and
      "columnPicker.applyToFolderAndChildren.label" options. This item indicates
      a desire to apply the currently displayed set of columns to some other
      folder(s). The sub-menu items indicate whether we want to apply it to just
      a folder or also its children.
   -->
@@ -854,17 +848,16 @@
      in that popup is given this label to indicate that that folder should be
      selected. For example, if folder "A" has two children, "B" and "C", then
      when the user hovers over "A", a new popup menu will be displayed whose
      items are "This folder", "B", and "C". This is the equivalent of the
      "File here" option for the move to/copy to widget.
   -->
 <!ENTITY columnPicker.thisFolder.label "This folder">
 
-
 <!-- Media (video/audio) controls -->
 <!ENTITY contextPlay.label "Play">
 <!ENTITY contextPlay.accesskey "P">
 <!ENTITY contextPause.label "Pause">
 <!ENTITY contextPause.accesskey "P">
 <!ENTITY contextMute.label "Mute">
 <!ENTITY contextMute.accesskey "M">
 <!ENTITY contextUnmute.label "Unmute">
--- a/mail/test/mozmill/folder-display/test-columns.js
+++ b/mail/test/mozmill/folder-display/test-columns.js
@@ -349,78 +349,77 @@ function test_column_reordering_persists
 function invoke_column_picker_option(aActions) {
   // The treecolpicker element itself doesn't have an id, so we have to walk
   // down from the parent to find it.
   //  treadCols
   //   |- hbox                item 0
   //   |- treecolpicker   <-- item 1 this is the one we want
   let threadCols = mc.window.document.getElementById("threadCols");
   let colPicker = threadCols.querySelector("treecolpicker");
-  let colPickerPopup = mc.window.document.getAnonymousElementByAttribute(
-                         colPicker, "anonid", "popup");
+  let colPickerPopup = colPicker.querySelector("[anonid=popup]");
 
   mc.click(new elib.Elem(colPicker));
   mc.click_menus_in_sequence(colPickerPopup, aActions);
 }
 
 
 /**
  * The column picker's "reset columns to default" option should set our state
- *  back to inbox state.
+ *  back to the natural state.
  */
-function disabled_test_reset_to_inbox() {
+function test_reset_to_inbox() {
   // create the source
   folderSource = create_folder("ColumnsApplySource");
   // it better have INBOX defaults
   assert_visible_columns(INBOX_DEFAULTS);
 
   // permute them
   let conExtra = INBOX_DEFAULTS.concat(["sizeCol"]);
   show_column("sizeCol");
   assert_visible_columns(conExtra);
 
   // reset!
-  invoke_column_picker_option([{anonid: "reset"}]);
+  invoke_column_picker_option([{anonid: "menuitem"}]);
 }
 
 function subtest_say_yes(cwc) {
   cwc.window.document.documentElement.getButton('accept').doCommand();
 }
 
 function _apply_to_folder_common(aChildrenToo, folder) {
   if (aChildrenToo)
     plan_for_observable_event("msg-folder-columns-propagated");
   plan_for_modal_dialog("commonDialog", subtest_say_yes);
-  invoke_column_picker_option([{anonid: "applyTo-menu"},
-                               {anonid: aChildrenToo ?
+  invoke_column_picker_option([{class: "applyTo-menu"},
+                               {class: aChildrenToo ?
                                   "applyToFolderAndChildren-menu" :
                                   "applyToFolder-menu"},
                                {label: "Local Folders"},
                                {label: folder.name},
                                {label: folder.name}]);
   wait_for_modal_dialog("commonDialog");
   if (aChildrenToo)
     wait_for_observable_event("msg-folder-columns-propagated");
 }
 
 /**
  * Change settings in a folder, apply them to another folder that also has
  *  children.  Make sure the folder changes but the children do not.
  */
-function disabled_test_apply_to_folder_no_children() {
+function test_apply_to_folder_no_children() {
   folderParent = create_folder("ColumnsApplyParent");
   folderParent.createSubfolder("Child1", null);
   folderChild1 = folderParent.getChildNamed("Child1");
   folderParent.createSubfolder("Child2", null);
   folderChild2 = folderParent.getChildNamed("Child2");
 
   be_in_folder(folderSource);
 
   // reset!
-  invoke_column_picker_option([{anonid: "reset"}]);
+  invoke_column_picker_option([{anonid: "menuitem"}]);
 
   // permute!
   let conExtra = INBOX_DEFAULTS.concat(["sizeCol"]);
   show_column("sizeCol");
   assert_visible_columns(conExtra);
 
   // apply to the one dude
   _apply_to_folder_common(false, folderParent);
@@ -435,24 +434,24 @@ function disabled_test_apply_to_folder_n
   be_in_folder(folderChild2);
   assert_visible_columns(INBOX_DEFAULTS);
 }
 
 /**
  * Change settings in a folder, apply them to another folder and its children.
  *  Make sure the folder and its children change.
  */
-function disabled_test_apply_to_folder_and_children() {
+function test_apply_to_folder_and_children() {
   // no need to throttle ourselves during testing.
   MailUtils.INTER_FOLDER_PROCESSING_DELAY_MS = 0;
 
   be_in_folder(folderSource);
 
   // reset!
-  invoke_column_picker_option([{anonid: "reset"}]);
+  invoke_column_picker_option([{anonid: "menuitem"}]);
 
   // permute!
   let conExtra = INBOX_DEFAULTS.concat(["tagsCol"]);
   show_column("tagsCol");
   assert_visible_columns(conExtra);
 
   // apply to the dude and his offspring
   _apply_to_folder_common(true, folderParent);
@@ -460,34 +459,35 @@ function disabled_test_apply_to_folder_a
   // make sure it copied to the parent and his children
   be_in_folder(folderParent);
   assert_visible_columns(conExtra);
   be_in_folder(folderChild1);
   assert_visible_columns(conExtra);
   be_in_folder(folderChild2);
   assert_visible_columns(conExtra);
 }
-disabled_test_apply_to_folder_and_children.EXCLUDED_PLATFORMS = ['linux'];  // See bug 1406717.
+test_apply_to_folder_and_children.EXCLUDED_PLATFORMS = ['linux'];  // See bug 1406717.
+test_apply_to_folder_and_children.__force_skip__ = true;  // See bug 1521016.
 
 /**
  * Change settings in an incoming folder, apply them to an outgoing folder that
  * also has children. Make sure the folder changes but the children do not.
  */
-function disabled_test_apply_to_folder_no_children_swapped() {
+function test_apply_to_folder_no_children_swapped() {
   folderParent = create_folder("ColumnsApplyParentOutgoing");
   folderParent.setFlag(Ci.nsMsgFolderFlags.SentMail);
   folderParent.createSubfolder("Child1", null);
   folderChild1 = folderParent.getChildNamed("Child1");
   folderParent.createSubfolder("Child2", null);
   folderChild2 = folderParent.getChildNamed("Child2");
 
   be_in_folder(folderSource);
 
   // reset!
-  invoke_column_picker_option([{anonid: "reset"}]);
+  invoke_column_picker_option([{anonid: "menuitem"}]);
 
   // permute!
   let conExtra = [...INBOX_DEFAULTS];
   if (useCorrespondent) {
     conExtra[5] = "senderCol";
     hide_column("correspondentCol");
     show_column("senderCol");
   } else {
@@ -507,30 +507,31 @@ function disabled_test_apply_to_folder_n
   assert_visible_columns(conExtraSwapped);
 
   // But not the children.
   be_in_folder(folderChild1);
   assert_visible_columns(SENT_DEFAULTS);
   be_in_folder(folderChild2);
   assert_visible_columns(SENT_DEFAULTS);
 }
-disabled_test_apply_to_folder_no_children_swapped.EXCLUDED_PLATFORMS = ['linux'];  // See bug 1406717.
+test_apply_to_folder_no_children_swapped.EXCLUDED_PLATFORMS = ['linux'];  // See bug 1406717.
+test_apply_to_folder_no_children_swapped.__force_skip__ = true;  // See bug 1521016.
 
 /**
  * Change settings in an incoming folder, apply them to an outgoing folder and
  * its children. Make sure the folder and its children change.
  */
-function disabled_test_apply_to_folder_and_children_swapped() {
+function test_apply_to_folder_and_children_swapped() {
   // No need to throttle ourselves during testing.
   MailUtils.INTER_FOLDER_PROCESSING_DELAY_MS = 0;
 
   be_in_folder(folderSource);
 
   // reset!
-  invoke_column_picker_option([{anonid: "reset"}]);
+  invoke_column_picker_option([{anonid: "menuitem"}]);
 
   // permute!
   let conExtra = [...INBOX_DEFAULTS];
   if (useCorrespondent) {
     conExtra[5] = "senderCol";
     hide_column("correspondentCol");
     show_column("senderCol");
   } else {
@@ -548,18 +549,18 @@ function disabled_test_apply_to_folder_a
   conExtraSwapped[5] = useCorrespondent ? "recipientCol" : "correspondentCol";
   be_in_folder(folderParent);
   assert_visible_columns(conExtraSwapped);
   be_in_folder(folderChild1);
   assert_visible_columns(conExtraSwapped);
   be_in_folder(folderChild2);
   assert_visible_columns(conExtraSwapped);
 }
-disabled_test_apply_to_folder_and_children_swapped.EXCLUDED_PLATFORMS = ['linux'];  // See bug 1406717.
-
+test_apply_to_folder_and_children_swapped.EXCLUDED_PLATFORMS = ['linux'];  // See bug 1406717.
+test_apply_to_folder_and_children_swapped.__force_skip__ = true;  // See bug 1521016.
 
 /**
  * Create a fake gloda collection.
  */
 function FakeCollection() {
   this.items = [];
 }
 
@@ -600,21 +601,21 @@ function test_persist_columns_gloda_coll
   glodaColumns = GLODA_DEFAULTS.slice(0, -1);
   glodaColumns.push("accountCol");
 
   mc.tabmail.openTab("glodaList", { collection: fakeCollection });
   wait_for_all_messages_to_load();
   assert_visible_columns(glodaColumns);
 }
 
-function disabled_test_reset_columns_gloda_collection() {
+function test_reset_columns_gloda_collection() {
   let fakeCollection = new FakeCollection();
   mc.tabmail.openTab("glodaList", { collection: fakeCollection });
   wait_for_all_messages_to_load();
   assert_visible_columns(glodaColumns);
 
-  invoke_column_picker_option([{anonid: "reset"}]);
-  assert_visible_columns(GLODA_DEFAULTS);
+  invoke_column_picker_option([{anonid: "menuitem"}]); // reset!
+  assert_visible_columns(glodaColumns); // same, only order (would be) reset
 
   mc.tabmail.openTab("glodaList", { collection: fakeCollection });
   wait_for_all_messages_to_load();
-  assert_visible_columns(GLODA_DEFAULTS);
+  assert_visible_columns(glodaColumns);
 }
--- a/mail/test/mozmill/folder-display/test-right-click-middle-click-messages.js
+++ b/mail/test/mozmill/folder-display/test-right-click-middle-click-messages.js
@@ -73,18 +73,17 @@ function test_right_click_column_header_
 
   // The treecolpicker element itself doesn't have an id, so we have to walk
   // down from the parent to find it.
   //  treadCols
   //   |- hbox                item 0
   //   |- treecolpicker   <-- item 1 this is the one we want
   let threadCols = mc.window.document.getElementById("threadCols");
   let treeColPicker = threadCols.querySelector("treecolpicker");
-  let popup = mc.window.document.getAnonymousElementByAttribute(
-                treeColPicker, "anonid", "popup");
+  let popup = treeColPicker.querySelector("[anonid=popup]");
 
   // Right click the subject column header
   // This should show the column picker popup.
   mc.rightClick(mc.eid("subjectCol"));
 
   // Check that the popup opens.
   wait_for_popup_to_open(popup);
   // Hide it again, we just wanted to know it was gonna be shown.
--- a/mail/test/mozmill/shared-modules/test-window-helpers.js
+++ b/mail/test/mozmill/shared-modules/test-window-helpers.js
@@ -1763,18 +1763,17 @@ function augment_controller(aController,
     for (let i = 0; i < treecolses.length; i++) {
       let treecols = treecolses[i];
       // The treecolpicker element itself doesn't have an id, so we have to walk
       // down from the parent to find it.
       //  treadCols
       //   |- hbox                item 0
       //   |- treecolpicker   <-- item 1 this is the one we want
       let treeColPicker = treecols.querySelector("treecolpicker");
-      let popup = doc.getAnonymousElementByAttribute(treeColPicker,
-                                                     "anonid", "popup");
+      let popup = treeColPicker.querySelector(`menupopup[anonid="popup"]`);
       popup.addEventListener("popupshowing", __popup_showing, true);
       popup.addEventListener("popupshown", __popup_shown, true);
       popup.addEventListener("popuphiding", __popup_hiding, true);
       popup.addEventListener("popuphidden", __popup_hidden, true);
     }
 
   }
   catch(ex) {