Bug 1522778 - Remove prefwindow and preftab bindings. r=aceman a=jorgk
authorGeoff Lankow <geoff@darktrojan.net>
Tue, 29 Jan 2019 10:54:10 +1300
changeset 34326 96ed115c265a
parent 34325 7759b93fc8dd
child 34327 fe791ff3dc62
push id389
push userclokep@gmail.com
push dateMon, 18 Mar 2019 19:01:53 +0000
reviewersaceman, jorgk
bugs1522778
Bug 1522778 - Remove prefwindow and preftab bindings. r=aceman a=jorgk
calendar/lightning/content/messenger-overlay-preferences.xul
calendar/test/mozmill/shared-modules/test-calendar-utils.js
common/bindings/preferences.xml
mail/base/content/macMessengerMenu.js
mail/base/content/messenger.css
mail/components/preferences/aboutPreferences.xml
mail/components/preferences/aboutPreferences.xul
mail/components/preferences/chat.js
mail/components/preferences/display.js
mail/components/preferences/jar.mn
mail/components/preferences/preferences.css
mail/components/preferences/preferences.js
mail/components/preferences/subdialogs.js
mail/test/mozmill/pref-window/test-font-chooser.js
mail/test/mozmill/shared-modules/test-pref-window-helpers.js
mail/themes/linux/mail/preferences/aboutPreferences.css
mail/themes/linux/mail/preferences/preferences.css
mail/themes/osx/mail/preferences/aboutPreferences.css
mail/themes/osx/mail/preferences/preferences.css
mail/themes/shared/mail/incontentprefs/aboutPreferences.css
mail/themes/windows/mail/preferences/aboutPreferences.css
mail/themes/windows/mail/preferences/preferences.css
--- a/calendar/lightning/content/messenger-overlay-preferences.xul
+++ b/calendar/lightning/content/messenger-overlay-preferences.xul
@@ -10,17 +10,16 @@
     %lightningDTD;
     %preferencesDTD;
 ]>
 
 <?xml-stylesheet href="chrome://lightning/skin/lightning.css"?>
 
 <overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
 
-    <prefwindow id="MailPreferences">
         <prefpane id="paneLightning"
                   flex="1"
                   insertbefore="paneAdvanced"
                   label="&lightning.preferencesLabel;">
             <preferences>
                 <preference id="calendar.preferences.lightning.selectedTabIndex"
                             name="calendar.preferences.lightning.selectedTabIndex"
                             type="int"/>
@@ -49,14 +48,12 @@
                     </tabpanel>
                     <tabpanel orient="vertical">
                         <vbox id="calPreferencesBoxViews"/>
                     </tabpanel>
                 </tabpanels>
             </tabbox>
         </prefpane>
 
-    </prefwindow>
-
     <script type="application/javascript"
             src="chrome://lightning/content/messenger-overlay-preferences.js"/>
 
 </overlay>
--- a/calendar/test/mozmill/shared-modules/test-calendar-utils.js
+++ b/calendar/test/mozmill/shared-modules/test-calendar-utils.js
@@ -622,21 +622,20 @@ function findEventsInNode(node, eventNod
         }
     }
 }
 
 function openLightningPrefs(aCallback, aParentController) {
     // Since the Lightning pane is added after load, asking for it with open_pref_tab won't work.
     // Cheat instead.
     let tab = open_pref_tab("paneGeneral");
-    let categoryBox = tab.browser.contentDocument.getAnonymousElementByAttribute(
-        tab.browser.contentDocument.documentElement, "id", "pref-category-box");
+    let categoryBox = tab.browser.contentDocument.getElementById("pref-category-box");
     categoryBox.querySelector('radio[pane="paneLightning"]').click();
     utils.waitFor(
-        () => tab.browser.contentDocument.documentElement.currentPane.id == "paneLightning",
+        () => tab.browser.contentWindow.getCurrentPaneID() == "paneLightning",
         "Timed out waiting for prefpane paneLightning to load."
     );
     aCallback(tab);
 }
 
 /**
  * Helper to work around a mac bug in Thunderbird's mozmill version. This can
  * likely be removed with Mozmill 2.0's new Element Object.
--- a/common/bindings/preferences.xml
+++ b/common/bindings/preferences.xml
@@ -173,24 +173,26 @@
           this._value = preference ? preference.value : this.valueFromPreferences;
         } else {
           this._value = this.valueFromPreferences;
         }
         if (this.preferences._constructAfterChildrenCalled) {
           // This <preference> was added after _constructAfterChildren() was already called.
           // We can directly call updateElements().
           this.updateElements();
-          return;
+        } else {
+          this.preferences._constructedChildrenCount++;
+          if (this.preferences._constructedChildrenCount ==
+              this.preferences._preferenceChildren.length) {
+            // This is the last <preference>, time to updateElements() on all of them.
+            this.preferences._constructAfterChildren();
+          }
         }
-        this.preferences._constructedChildrenCount++;
-        if (this.preferences._constructedChildrenCount ==
-            this.preferences._preferenceChildren.length) {
-          // This is the last <preference>, time to updateElements() on all of them.
-          this.preferences._constructAfterChildren();
-        }
+
+        this.dispatchEvent(new CustomEvent("bindingattached", { bubbles: false }));
       ]]>
       </constructor>
       <destructor>
         this.preferences.rootBranchInternal
             .removeObserver(this.name, this.preferences);
       </destructor>
       <field name="_constructed">false</field>
       <property name="instantApply">
@@ -585,580 +587,16 @@
 
     <handlers>
       <handler event="change">
         this.updateElements();
       </handler>
     </handlers>
   </binding>
 
-  <binding id="prefwindow"
-           extends="chrome://global/content/bindings/dialog.xml#dialog">
-    <content dlgbuttons="accept,cancel" persist="lastSelected screenX screenY"
-             closebuttonlabel="&preferencesCloseButton.label;"
-             closebuttonaccesskey="&preferencesCloseButton.accesskey;"
-             role="dialog"
-#ifdef XP_WIN
-             title="&preferencesDefaultTitleWin.title;">
-#else
-             title="&preferencesDefaultTitleMac.title;">
-#endif
-      <xul:vbox orient="vertical">
-        <xul:radiogroup anonid="selector" orient="horizontal" class="paneSelector chromeclass-toolbar"
-                        role="listbox"/> <!-- Expose to accessibility APIs as a listbox -->
-      </xul:vbox>
-      <xul:hbox flex="1" class="paneDeckContainer">
-        <xul:deck anonid="paneDeck" flex="1">
-          <children includes="prefpane"/>
-        </xul:deck>
-      </xul:hbox>
-      <xul:hbox anonid="dlg-buttons" class="prefWindow-dlgbuttons" pack="end">
-#ifdef XP_UNIX
-        <xul:button dlgtype="disclosure" class="dialog-button" hidden="true"/>
-        <xul:button dlgtype="help" class="dialog-button" hidden="true" icon="help"/>
-        <xul:button dlgtype="extra2" class="dialog-button" hidden="true"/>
-        <xul:button dlgtype="extra1" class="dialog-button" hidden="true"/>
-        <xul:spacer anonid="spacer" flex="1"/>
-        <xul:button dlgtype="cancel" class="dialog-button" icon="cancel"/>
-        <xul:button dlgtype="accept" class="dialog-button" icon="accept"/>
-#else
-        <xul:button dlgtype="extra2" class="dialog-button" hidden="true"/>
-        <xul:spacer anonid="spacer" flex="1"/>
-        <xul:button dlgtype="accept" class="dialog-button" icon="accept"/>
-        <xul:button dlgtype="extra1" class="dialog-button" hidden="true"/>
-        <xul:button dlgtype="cancel" class="dialog-button" icon="cancel"/>
-        <xul:button dlgtype="help" class="dialog-button" hidden="true" icon="help"/>
-        <xul:button dlgtype="disclosure" class="dialog-button" hidden="true"/>
-#endif
-      </xul:hbox>
-      <xul:hbox>
-        <children/>
-      </xul:hbox>
-    </content>
-    <implementation implements="nsITimerCallback">
-      <constructor>
-      <![CDATA[
-        if (this.type != "child") {
-          if (!this._instantApplyInitialized) {
-            let psvc = Cc["@mozilla.org/preferences-service;1"]
-                         .getService(Ci.nsIPrefBranch);
-            this.instantApply = psvc.getBoolPref("browser.preferences.instantApply");
-          }
-          if (this.instantApply) {
-            var docElt = document.documentElement;
-            var acceptButton = docElt.getButton("accept");
-            acceptButton.hidden = true;
-            var cancelButton = docElt.getButton("cancel");
-            if (/Mac/.test(navigator.platform)) {
-              // no buttons on Mac except Help
-              cancelButton.hidden = true;
-              // Move Help button to the end
-              document.getAnonymousElementByAttribute(this, "anonid", "spacer").hidden = true;
-              // Also, don't fire onDialogAccept on enter
-              acceptButton.disabled = true;
-            } else {
-              // morph the Cancel button into the Close button
-              cancelButton.setAttribute("icon", "close");
-              cancelButton.label = docElt.getAttribute("closebuttonlabel");
-              cancelButton.accesskey = docElt.getAttribute("closebuttonaccesskey");
-            }
-          }
-        }
-        this.setAttribute("animated", this._shouldAnimate ? "true" : "false");
-        var panes = this.preferencePanes;
-
-        var lastPane = null;
-        if (this.lastSelected) {
-          lastPane = document.getElementById(this.lastSelected);
-          if (!lastPane) {
-            this.lastSelected = "";
-          }
-        }
-
-        for (var i = 0; i < panes.length; ++i) {
-          this._makePaneButton(panes[i]);
-          if (panes[i].loaded) {
-            // Inline pane content, fire load event to force initialization.
-            this._fireEvent("paneload", panes[i]);
-          }
-        }
-
-        this.showPane(lastPane || panes[0]);
-
-        if (panes.length == 1)
-          this._selector.setAttribute("collapsed", "true");
-      ]]>
-      </constructor>
-
-      <destructor>
-      <![CDATA[
-        // Release timers to avoid reference cycles.
-        if (this._animateTimer) {
-          this._animateTimer.cancel();
-          this._animateTimer = null;
-        }
-        if (this._fadeTimer) {
-          this._fadeTimer.cancel();
-          this._fadeTimer = null;
-        }
-      ]]>
-      </destructor>
-
-      <!-- Derived bindings can set this to true to cause us to skip
-           reading the browser.preferences.instantApply pref in the constructor.
-           Then they can set instantApply to their wished value. -->
-      <field name="_instantApplyInitialized">false</field>
-      <!-- Controls whether changed pref values take effect immediately. -->
-      <field name="instantApply">false</field>
-
-      <property name="preferencePanes"
-                onget="return this.getElementsByTagName('prefpane');"/>
-
-      <property name="type" onget="return this.getAttribute('type');"/>
-      <property name="_paneDeck"
-                onget="return document.getAnonymousElementByAttribute(this, 'anonid', 'paneDeck');"/>
-      <property name="_paneDeckContainer"
-                onget="return document.getAnonymousElementByAttribute(this, 'class', 'paneDeckContainer');"/>
-      <property name="_selector"
-                onget="return document.getAnonymousElementByAttribute(this, 'anonid', 'selector');"/>
-      <property name="lastSelected"
-                onget="return this.getAttribute('lastSelected');">
-        <setter>
-          /* globals Services */
-          this.setAttribute("lastSelected", val);
-          Services.xulStore.persist(this, "lastSelected");
-          return val;
-        </setter>
-      </property>
-      <property name="currentPane"
-                onset="return this._currentPane = val;">
-        <getter>
-          if (!this._currentPane)
-            this._currentPane = this.preferencePanes[0];
-
-          return this._currentPane;
-        </getter>
-      </property>
-      <field name="_currentPane">null</field>
-
-
-      <method name="_makePaneButton">
-        <parameter name="aPaneElement"/>
-        <body>
-        <![CDATA[
-          var radio = document.createElement("radio");
-          radio.setAttribute("pane", aPaneElement.id);
-          radio.setAttribute("value", aPaneElement.id);
-          radio.setAttribute("label", aPaneElement.label);
-          // Expose preference group choice to accessibility APIs as an unchecked list item
-          // The parent group is exposed to accessibility APIs as a list
-          if (aPaneElement.image)
-            radio.setAttribute("src", aPaneElement.image);
-          radio.style.listStyleImage = aPaneElement.style.listStyleImage;
-          this._selector.appendChild(radio);
-          return radio;
-        ]]>
-        </body>
-      </method>
-
-      <method name="showPane">
-        <parameter name="aPaneElement"/>
-        <body>
-        <![CDATA[
-          if (!aPaneElement)
-            return;
-
-          this._selector.selectedItem = document.getAnonymousElementByAttribute(this, "pane", aPaneElement.id);
-          if (!aPaneElement.loaded) {
-            let OverlayLoadObserver = function(aPane) {
-              this._pane = aPane;
-            };
-            OverlayLoadObserver.prototype = {
-              _outer: this,
-              observe(aSubject, aTopic, aData) {
-                this._pane.loaded = true;
-                this._outer._fireEvent("paneload", this._pane);
-                this._outer._selectPane(this._pane);
-              },
-            };
-
-            var obs = new OverlayLoadObserver(aPaneElement);
-            document.loadOverlay(aPaneElement.src, obs);
-          } else {
-            this._selectPane(aPaneElement);
-          }
-        ]]>
-        </body>
-      </method>
-
-      <method name="_fireEvent">
-        <parameter name="aEventName"/>
-        <parameter name="aTarget"/>
-        <body>
-        <![CDATA[
-          // Panel loaded, synthesize a load event.
-          try {
-            var event = document.createEvent("Events");
-            event.initEvent(aEventName, true, true);
-            var cancel = !aTarget.dispatchEvent(event);
-            if (aTarget.hasAttribute("on" + aEventName)) {
-              var fn = new Function("event", aTarget.getAttribute("on" + aEventName));
-              var rv = fn.call(aTarget, event);
-              if (!rv)
-                cancel = true;
-            }
-            return !cancel;
-          } catch (e) {
-            Cu.reportError(e);
-          }
-          return false;
-        ]]>
-        </body>
-      </method>
-
-      <field name="_initialized">false</field>
-      <method name="_selectPane">
-        <parameter name="aPaneElement"/>
-        <body>
-        <![CDATA[
-          if (/Mac/.test(navigator.platform)) {
-            var paneTitle = aPaneElement.label;
-            if (paneTitle != "")
-              document.title = paneTitle;
-          }
-          var helpButton = document.documentElement.getButton("help");
-          if (aPaneElement.helpTopic)
-            helpButton.hidden = false;
-          else
-            helpButton.hidden = true;
-
-          // Find this pane's index in the deck and set the deck's
-          // selectedIndex to that value to switch to it.
-          var prefpanes = this.preferencePanes;
-          for (var i = 0; i < prefpanes.length; ++i) {
-            if (prefpanes[i] == aPaneElement) {
-              this._paneDeck.selectedIndex = i;
-
-              if (this.type != "child") {
-                if (aPaneElement.hasAttribute("flex") && this._shouldAnimate &&
-                    prefpanes.length > 1)
-                  aPaneElement.removeAttribute("flex");
-                // Calling sizeToContent after the first prefpane is loaded
-                // will size the windows contents so style information is
-                // available to calculate correct sizing.
-                if (!this._initialized && prefpanes.length > 1) {
-                  if (this._shouldAnimate)
-                    this.style.minHeight = 0;
-                  window.sizeToContent();
-                }
-
-                var oldPane = this.lastSelected ? document.getElementById(this.lastSelected) : this.preferencePanes[0];
-                oldPane.selected = !(aPaneElement.selected = true);
-                this.lastSelected = aPaneElement.id;
-                this.currentPane = aPaneElement;
-                this._initialized = true;
-
-                // Only animate if we've switched between prefpanes
-                if (this._shouldAnimate && oldPane.id != aPaneElement.id) {
-                  aPaneElement.style.opacity = 0.0;
-                  this.animate(oldPane, aPaneElement);
-                } else if (!this._shouldAnimate && prefpanes.length > 1) {
-                  var targetHeight = parseInt(window.getComputedStyle(this._paneDeckContainer).height);
-                  var verticalPadding = parseInt(window.getComputedStyle(aPaneElement).paddingTop);
-                  verticalPadding += parseInt(window.getComputedStyle(aPaneElement).paddingBottom);
-                  if (aPaneElement.contentHeight > targetHeight - verticalPadding) {
-                    // To workaround the bottom border of a groupbox from being
-                    // cutoff an hbox with a class of bottomBox may enclose it.
-                    // This needs to include its padding to resize properly.
-                    // See bug 394433
-                    var bottomPadding = 0;
-                    var bottomBox = aPaneElement.getElementsByAttribute("class", "bottomBox")[0];
-                    if (bottomBox)
-                      bottomPadding = parseInt(window.getComputedStyle(bottomBox).paddingBottom);
-                    window.innerHeight += bottomPadding + verticalPadding + aPaneElement.contentHeight - targetHeight;
-                  }
-                }
-              }
-              break;
-            }
-          }
-        ]]>
-        </body>
-      </method>
-
-      <property name="_shouldAnimate">
-        <getter>
-        <![CDATA[
-          var psvc = Cc["@mozilla.org/preferences-service;1"]
-                       .getService(Ci.nsIPrefBranch);
-          return psvc.getBoolPref("browser.preferences.animateFadeIn",
-                                  /Mac/.test(navigator.platform));
-        ]]>
-        </getter>
-      </property>
-
-      <method name="animate">
-        <parameter name="aOldPane"/>
-        <parameter name="aNewPane"/>
-        <body>
-        <![CDATA[
-          // if we are already resizing, use currentHeight
-          var oldHeight = this._currentHeight ? this._currentHeight : aOldPane.contentHeight;
-
-          this._multiplier = aNewPane.contentHeight > oldHeight ? 1 : -1;
-          var sizeDelta = Math.abs(oldHeight - aNewPane.contentHeight);
-          this._animateRemainder = sizeDelta % this._animateIncrement;
-
-          this._setUpAnimationTimer(oldHeight);
-        ]]>
-        </body>
-      </method>
-
-      <property name="_sizeIncrement">
-        <getter>
-        <![CDATA[
-          var lastSelectedPane = document.getElementById(this.lastSelected);
-          var increment = this._animateIncrement * this._multiplier;
-          var newHeight = this._currentHeight + increment;
-          if ((this._multiplier > 0 && this._currentHeight >= lastSelectedPane.contentHeight) ||
-              (this._multiplier < 0 && this._currentHeight <= lastSelectedPane.contentHeight))
-            return 0;
-
-          if ((this._multiplier > 0 && newHeight > lastSelectedPane.contentHeight) ||
-              (this._multiplier < 0 && newHeight < lastSelectedPane.contentHeight))
-            increment = this._animateRemainder * this._multiplier;
-          return increment;
-        ]]>
-        </getter>
-      </property>
-
-      <method name="notify">
-        <parameter name="aTimer"/>
-        <body>
-        <![CDATA[
-          if (!document)
-            aTimer.cancel();
-
-          if (aTimer == this._animateTimer) {
-            var increment = this._sizeIncrement;
-            if (increment != 0) {
-              window.innerHeight += increment;
-              this._currentHeight += increment;
-            } else {
-              aTimer.cancel();
-              this._setUpFadeTimer();
-            }
-          } else if (aTimer == this._fadeTimer) {
-            var elt = document.getElementById(this.lastSelected);
-            var newOpacity = parseFloat(window.getComputedStyle(elt).opacity) + this._fadeIncrement;
-            if (newOpacity < 1.0) {
-              elt.style.opacity = newOpacity;
-            } else {
-              aTimer.cancel();
-              elt.style.opacity = 1.0;
-            }
-          }
-        ]]>
-        </body>
-      </method>
-
-      <method name="_setUpAnimationTimer">
-        <parameter name="aStartHeight"/>
-        <body>
-        <![CDATA[
-          if (!this._animateTimer)
-            this._animateTimer = Cc["@mozilla.org/timer;1"]
-                                   .createInstance(Ci.nsITimer);
-          else
-            this._animateTimer.cancel();
-          this._currentHeight = aStartHeight;
-
-          this._animateTimer.initWithCallback(this, this._animateDelay,
-                                              Ci.nsITimer.TYPE_REPEATING_SLACK);
-        ]]>
-        </body>
-      </method>
-
-      <method name="_setUpFadeTimer">
-        <body>
-        <![CDATA[
-          if (!this._fadeTimer)
-            this._fadeTimer = Cc["@mozilla.org/timer;1"]
-                                .createInstance(Ci.nsITimer);
-          else
-            this._fadeTimer.cancel();
-
-          this._fadeTimer.initWithCallback(this, this._fadeDelay,
-                                           Ci.nsITimer.TYPE_REPEATING_SLACK);
-        ]]>
-        </body>
-      </method>
-
-      <field name="_animateTimer">null</field>
-      <field name="_fadeTimer">null</field>
-      <field name="_animateDelay">15</field>
-      <field name="_animateIncrement">40</field>
-      <field name="_fadeDelay">5</field>
-      <field name="_fadeIncrement">0.40</field>
-      <field name="_animateRemainder">0</field>
-      <field name="_currentHeight">0</field>
-      <field name="_multiplier">0</field>
-
-      <method name="addPane">
-        <parameter name="aPaneElement"/>
-        <body>
-        <![CDATA[
-          this.appendChild(aPaneElement);
-
-          // Set up pane button
-          this._makePaneButton(aPaneElement);
-        ]]>
-        </body>
-      </method>
-
-      <method name="openSubDialog">
-        <parameter name="aURL"/>
-        <parameter name="aFeatures"/>
-        <parameter name="aParams"/>
-        <body>
-          return openDialog(aURL, "", "modal,centerscreen,resizable=no" + (aFeatures != "" ? ("," + aFeatures) : ""), aParams);
-        </body>
-      </method>
-
-      <method name="openWindow">
-        <parameter name="aWindowType"/>
-        <parameter name="aURL"/>
-        <parameter name="aFeatures"/>
-        <parameter name="aParams"/>
-        <body>
-        <![CDATA[
-          var wm = Cc["@mozilla.org/appshell/window-mediator;1"]
-                     .getService(Ci.nsIWindowMediator);
-          var win = aWindowType ? wm.getMostRecentWindow(aWindowType) : null;
-          if (win) {
-            if ("initWithParams" in win)
-              win.initWithParams(aParams);
-            win.focus();
-          } else {
-            var features = "resizable,dialog=no,centerscreen" + (aFeatures != "" ? ("," + aFeatures) : "");
-            var parentWindow = (this.instantApply || !window.opener || window.opener.closed) ? window : window.opener;
-            win = parentWindow.openDialog(aURL, "_blank", features, aParams);
-          }
-          return win;
-        ]]>
-        </body>
-      </method>
-    </implementation>
-    <handlers>
-      <handler event="dialogaccept">
-      <![CDATA[
-        if (!this._fireEvent("beforeaccept", this)) {
-          return false;
-        }
-
-        var secMan = Cc["@mozilla.org/scriptsecuritymanager;1"]
-                    .getService(Ci.nsIScriptSecurityManager);
-        if (this.type == "child" && window.opener &&
-            secMan.isSystemPrincipal(window.opener.document.nodePrincipal)) {
-          var pdocEl = window.opener.document.documentElement;
-          if (pdocEl.instantApply) {
-            let panes = this.preferencePanes;
-            for (let i = 0; i < panes.length; ++i)
-              panes[i].writePreferences(true);
-          } else {
-            // Clone all the preferences elements from the child document and
-            // insert them into the pane collection of the parent.
-            var pdoc = window.opener.document;
-            if (pdoc.documentElement.localName == "prefwindow") {
-              var currentPane = pdoc.documentElement.currentPane;
-              var id = window.location.href + "#childprefs";
-              var childPrefs = pdoc.getElementById(id);
-              if (!childPrefs) {
-                childPrefs = pdoc.createElement("preferences");
-                currentPane.appendChild(childPrefs);
-                childPrefs.id = id;
-              }
-              let panes = this.preferencePanes;
-              for (let i = 0; i < panes.length; ++i) {
-                var preferences = panes[i].preferences;
-                for (var j = 0; j < preferences.length; ++j) {
-                  // Try to find a preference element for the same preference.
-                  var preference = null;
-                  var parentPreferences = pdoc.getElementsByTagName("preferences");
-                  for (var k = 0; (k < parentPreferences.length && !preference); ++k) {
-                    var parentPrefs = parentPreferences[k]
-                                         .getElementsByAttribute("name", preferences[j].name);
-                    for (var l = 0; (l < parentPrefs.length && !preference); ++l) {
-                      if (parentPrefs[l].localName == "preference")
-                        preference = parentPrefs[l];
-                    }
-                  }
-                  if (!preference) {
-                    // No matching preference in the parent window.
-                    preference = pdoc.createElement("preference");
-                    childPrefs.appendChild(preference);
-                    preference.name     = preferences[j].name;
-                    preference.type     = preferences[j].type;
-                    preference.inverted = preferences[j].inverted;
-                    preference.readonly = preferences[j].readonly;
-                    preference.disabled = preferences[j].disabled;
-                  }
-                  preference.value = preferences[j].value;
-                }
-              }
-            }
-          }
-        } else {
-          let panes = this.preferencePanes;
-          for (var i = 0; i < panes.length; ++i)
-            panes[i].writePreferences(false);
-
-          let psvc = Cc["@mozilla.org/preferences-service;1"]
-                       .getService(Ci.nsIPrefService);
-          psvc.savePrefFile(null);
-        }
-
-        return true;
-      ]]>
-      </handler>
-      <handler event="command">
-        if (event.originalTarget.hasAttribute("pane")) {
-          var pane = document.getElementById(event.originalTarget.getAttribute("pane"));
-          this.showPane(pane);
-        }
-      </handler>
-
-      <handler event="keypress" key="&windowClose.key;" modifiers="accel" phase="capturing">
-      <![CDATA[
-        if (this.instantApply)
-          window.close();
-        event.stopPropagation();
-        event.preventDefault();
-      ]]>
-      </handler>
-
-      <handler event="keypress"
-#ifdef XP_MACOSX
-               key="&openHelpMac.commandkey;" modifiers="accel"
-#else
-               keycode="&openHelp.commandkey;"
-#endif
-               phase="capturing">
-      <![CDATA[
-        var helpButton = this.getButton("help");
-        if (helpButton.disabled || helpButton.hidden)
-          return;
-        this._fireEvent("dialoghelp", this);
-        event.stopPropagation();
-        event.preventDefault();
-      ]]>
-      </handler>
-    </handlers>
-  </binding>
-
   <binding id="prefpane">
     <implementation>
       <method name="writePreferences">
         <parameter name="aFlushToDisk"/>
         <body>
         <![CDATA[
           // Write all values to preferences.
           if (this._deferredValueUpdateElements.size) {
--- a/mail/base/content/macMessengerMenu.js
+++ b/mail/base/content/macMessengerMenu.js
@@ -22,21 +22,19 @@ addEventListener("load", function() {
 }, false);
 
 /**
  * When the Preferences window is actually loaded, this Listener is called.
  * Not doing this way could make DOM elements not available.
  */
 function loadListener(event) {
   setTimeout(function() {
-    let preWin = Services.wm.getMostRecentWindow("Mail:Preferences");
-    preWin.document.documentElement
-          .openSubDialog("chrome://messenger/content/preferences/dockoptions.xul",
-                         "", null);
-  }, 0);
+    let prefWin = Services.wm.getMostRecentWindow("Mail:Preferences");
+    prefWin.gSubDialog.open("chrome://messenger/content/preferences/dockoptions.xul");
+  });
 }
 
 /**
  * When the Preferences window is opened/closed, this observer will be called.
  * This is done so subdialog opens as a child of it.
  */
 function PrefWindowObserver() {
   this.observe = function(aSubject, aTopic, aData) {
@@ -53,22 +51,20 @@ function PrefWindowObserver() {
  * If Preference window was already opened, this will select General pane before
  * opening Dock Options sub-dialog.
  */
 function openDockOptions() {
   let win = Services.wm.getMostRecentWindow("Mail:Preferences");
 
   if (win) {
     openOptionsDialog("paneGeneral");
-    win.document.documentElement
-       .openSubDialog("chrome://messenger/content/preferences/dockoptions.xul",
-                      "", null);
+    win.gSubDialog("chrome://messenger/content/preferences/dockoptions.xul");
   } else {
-      Services.ww.registerNotification(new PrefWindowObserver());
-      openOptionsDialog("paneGeneral");
+    Services.ww.registerNotification(new PrefWindowObserver());
+    openOptionsDialog("paneGeneral");
   }
 }
 
 /**
  * Open a new window for writing a new message
  */
 function writeNewMessageDock() {
   // Default identity will be used as sender for the new message.
--- a/mail/base/content/messenger.css
+++ b/mail/base/content/messenger.css
@@ -210,24 +210,16 @@ toolbar[type="menubar"][autohide="true"]
 
 toolbar[type="menubar"][autohide="true"][inactive="true"]:not([customizing="true"]) {
   min-height: 0 !important;
   height: 0 !important;
   -moz-appearance: none !important;
 }
 %endif
 
-/* Preferences */
-
-preftab,
-preftab:root /* override :root */ {
-  -moz-binding: url("chrome://messenger/content/preferences/aboutPreferences.xml#preftab");
-  -moz-box-orient: vertical;
-}
-
 /* WebExtensions icon-variables */
 
 :root[lwthemeicons~="--getmsg-icon"] #button-getmsg:-moz-lwtheme {
   list-style-image: var(--getmsg-icon) !important;
 }
 
 :root[lwthemeicons~="--newmsg-icon"] #button-newmsg:-moz-lwtheme,
 :root[lwthemeicons~="--newmsg-icon"] #button-newmessage:-moz-lwtheme {
deleted file mode 100644
--- a/mail/components/preferences/aboutPreferences.xml
+++ /dev/null
@@ -1,132 +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/. -->
-
-<!DOCTYPE bindings [
-  <!ENTITY % preferencesDTD SYSTEM "chrome://messenger/locale/preferences/preferences.dtd">
-  %preferencesDTD;
-  <!ENTITY % globalKeysDTD SYSTEM "chrome://global/locale/globalKeys.dtd">
-  %globalKeysDTD;
-]>
-
-<bindings id="preferencesBindings"
-          xmlns="http://www.mozilla.org/xbl"
-          xmlns:xbl="http://www.mozilla.org/xbl"
-          xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
-
-  <binding id="preftab"
-           extends="chrome://messenger/content/preferences/preferences.xml#prefwindow">
-    <content dlgbuttons="accept,cancel" persist="lastSelected"
-             closebuttonlabel="&preferencesCloseButton.label;"
-             closebuttonaccesskey="&preferencesCloseButton.accesskey;"
-             role="dialog">
-      <xul:stack flex="1">
-        <xul:hbox id="prefBox" flex="1">
-          <xul:vbox id="pref-category-box">
-            <xul:radiogroup anonid="selector" orient="vertical" class="paneSelector chromeclass-toolbar"
-                            role="listbox" flex="1"/> <!-- Expose to accessibility APIs as a listbox -->
-            <xul:spacer flex="1"/>
-            <xul:hbox class="sidebar-footer-button"
-                      pack="center"
-                      onclick="window.docShell.rootTreeItem.domWindow.openAddonsMgr();">
-            <xul:label id="addonsButton" class="text-link">
-              <xul:hbox align="center">
-                <xul:image class="sidebar-footer-icon addons-icon"/>
-                <xul:label class="sidebar-footer-label" flex="1">&addonsButton.label;</xul:label>
-              </xul:hbox>
-            </xul:label>
-          </xul:hbox>
-          </xul:vbox>
-          <xul:hbox id="preferencesContainer" flex="1">
-            <xul:hbox class="paneDeckContainer" flex="1">
-              <xul:deck anonid="paneDeck" flex="1">
-                <children includes="prefpane"/>
-              </xul:deck>
-            </xul:hbox>
-          </xul:hbox>
-        </xul:hbox>
-        <xul:stack id="dialogStack" hidden="true"/>
-        <xul:vbox id="dialogTemplate"
-                  class="dialogOverlay"
-                  align="center"
-                  pack="center"
-                  topmost="true"
-                  hidden="true">
-          <xul:vbox class="dialogBox"
-                    pack="end"
-                    role="dialog"
-                    aria-labelledby="dialogTitle">
-            <xul:hbox class="dialogTitleBar" align="center">
-              <xul:label class="dialogTitle" flex="1"/>
-              <xul:button class="dialogClose close-icon"
-                          aria-label="&preferencesCloseButton.label;"/>
-            </xul:hbox>
-            <xul:browser class="dialogFrame"
-                         autoscroll="false"
-                         disablehistory="true"/>
-            </xul:vbox>
-        </xul:vbox>
-      </xul:stack>
-      <xul:hbox anonid="dlg-buttons" class="prefWindow-dlgbuttons"
-                pack="end">
-        <xul:button dlgtype="extra2" class="dialog-button" hidden="true"/>
-        <xul:spacer anonid="spacer" flex="1"/>
-        <xul:button dlgtype="accept" class="dialog-button" icon="accept"/>
-        <xul:button dlgtype="extra1" class="dialog-button" hidden="true"/>
-        <xul:button dlgtype="cancel" class="dialog-button" icon="cancel"/>
-        <xul:button dlgtype="help" class="dialog-button" hidden="true" icon="help"/>
-        <xul:button dlgtype="disclosure" class="dialog-button" hidden="true"/>
-      </xul:hbox>
-      <xul:hbox>
-        <children/>
-      </xul:hbox>
-    </content>
-    <implementation>
-      <!-- Don't resize the window at Prefs opening -->
-      <field name="_initialized">true</field>
-      <!-- Don't resize the window at pane change -->
-      <field name="_shouldAnimate">false</field>
-      <!-- Always use instantApply in Prefs in Tab -->
-      <field name="_instantApplyInitialized">true</field>
-      <field name="instantApply">true</field>
-      <method name="_selectPane">
-        <parameter name="aPaneElement"/>
-        <body>
-        <![CDATA[
-          let helpButton = document.documentElement.getButton("help");
-          // If there's no topic, we don't need the help button.
-          helpButton.hidden = !aPaneElement.helpTopic;
-
-          // Find this pane's index in the deck and set the deck's
-          // selectedIndex to that value to switch to it.
-          let prefpanes = this.preferencePanes;
-          for (let i = 0; i < prefpanes.length; ++i) {
-            if (prefpanes[i] == aPaneElement) {
-              this._paneDeck.selectedIndex = i;
-              if (this.type != "child") {
-                let oldPane = this.lastSelected ? document.getElementById(this.lastSelected) : this.preferencePanes[0];
-                oldPane.selected = !(aPaneElement.selected = true);
-                this.lastSelected = aPaneElement.id;
-                this.currentPane = aPaneElement;
-
-                let targetHeight = parseInt(window.getComputedStyle(this._paneDeckContainer).height);
-                let verticalPadding = parseInt(window.getComputedStyle(aPaneElement).paddingTop);
-                verticalPadding += parseInt(window.getComputedStyle(aPaneElement).paddingBottom);
-                if (aPaneElement.contentHeight + verticalPadding < targetHeight)
-                  aPaneElement._content.style.height = targetHeight - verticalPadding + "px";
-              }
-              break;
-            }
-          }
-          let event = document.createEvent("Events");
-          event.initEvent("paneSelected", true, true);
-          this.currentPane.dispatchEvent(event);
-        ]]>
-        </body>
-      </method>
-    </implementation>
-  </binding>
-
-</bindings>
--- a/mail/components/preferences/aboutPreferences.xul
+++ b/mail/components/preferences/aboutPreferences.xul
@@ -37,24 +37,70 @@
                 src="chrome://messenger/locale/preferences/preferences.properties"/>
   <linkset>
     <link rel="localization" href="branding/brand.ftl"/>
     <link rel="localization" href="messenger/preferences/preferences.ftl"/>
     <link rel="localization" href="messenger/preferences/fonts.ftl"/>
     <link rel="localization" href="messenger/preferences/languages.ftl"/>
   </linkset>
 
-  <script type="application/javascript" src="chrome://messenger/content/customElements.js"/>
-  <script type="application/javascript" src="chrome://global/content/globalOverlay.js"/>
-  <script type="application/javascript" src="chrome://communicator/content/contentAreaClick.js"/>
-  <script type="application/javascript" src="chrome://messenger/content/preferences/preferences.js"/>
-  <script type="application/javascript" src="chrome://messenger/content/preferences/subdialogs.js"/>
-
+  <stack flex="1">
+    <hbox id="prefBox" flex="1">
+      <vbox id="pref-category-box">
+        <radiogroup id="selector" orient="vertical" class="paneSelector chromeclass-toolbar"
+                        role="listbox" flex="1"/> <!-- Expose to accessibility APIs as a listbox -->
+        <spacer flex="1"/>
+        <hbox class="sidebar-footer-button"
+              pack="center"
+              onclick="window.docShell.rootTreeItem.domWindow.openAddonsMgr();">
+          <label id="addonsButton" class="text-link">
+            <hbox align="center">
+              <image class="sidebar-footer-icon addons-icon"/>
+              <label class="sidebar-footer-label" flex="1">&addonsButton.label;</label>
+            </hbox>
+          </label>
+        </hbox>
+      </vbox>
+      <hbox id="preferencesContainer" flex="1">
+        <hbox class="paneDeckContainer" flex="1">
+          <deck id="paneDeck" flex="1">
 #include general.inc.xul
 #include display.inc.xul
 #include compose.inc.xul
 #include chat.inc.xul
 #include privacy.inc.xul
 #include security.inc.xul
 #include applications.inc.xul
-  <prefpane id="paneLightning" label="&paneLightning.title;"/>
+            <prefpane id="paneLightning" label="&paneLightning.title;"/>
 #include advanced.inc.xul
+          </deck>
+        </hbox>
+      </hbox>
+    </hbox>
+    <stack id="dialogStack" hidden="true"/>
+    <vbox id="dialogTemplate"
+          class="dialogOverlay"
+          align="center"
+          pack="center"
+          topmost="true"
+          hidden="true">
+      <vbox class="dialogBox"
+            pack="end"
+            role="dialog"
+            aria-labelledby="dialogTitle">
+        <hbox class="dialogTitleBar" align="center">
+          <label class="dialogTitle" flex="1"/>
+          <button class="dialogClose close-icon"
+                  aria-label="&preferencesCloseButton.label;"/>
+        </hbox>
+        <browser class="dialogFrame"
+                 autoscroll="false"
+                 disablehistory="true"/>
+      </vbox>
+    </vbox>
+  </stack>
+
+  <script type="application/javascript" src="chrome://messenger/content/customElements.js"/>
+  <script type="application/javascript" src="chrome://global/content/globalOverlay.js"/>
+  <script type="application/javascript" src="chrome://communicator/content/contentAreaClick.js"/>
+  <script type="application/javascript" src="chrome://messenger/content/preferences/preferences.js"/>
+  <script type="application/javascript" src="chrome://messenger/content/preferences/subdialogs.js"/>
 </preftab>
--- a/mail/components/preferences/chat.js
+++ b/mail/components/preferences/chat.js
@@ -36,17 +36,17 @@ var gChatPane = {
   },
 
   initPreview() {
     // We add this browser only when really necessary.
     let previewDeck = document.getElementById("previewDeck");
     if (previewDeck.querySelector("browser")) {
       return;
     }
-    if (getCurrentPaneID() != "paneChat") {
+    if (!("getCurrentPaneID" in window) || getCurrentPaneID() != "paneChat") {
       return;
     }
     if (this.mTabBox.selectedIndex != 1) {
       return;
     }
 
     window.removeEventListener("paneSelected", this.paneSelectionChanged);
 
--- a/mail/components/preferences/display.js
+++ b/mail/components/preferences/display.js
@@ -93,16 +93,22 @@ var gDisplayPane = {
                                                                  aLanguageGroup));
         if (!preference) {
           preference = document.createElement("preference");
           var name = prefs[i].format.replace(/%LANG%/, aLanguageGroup);
           preference.id = name;
           preference.setAttribute("name", name);
           preference.setAttribute("type", prefs[i].type);
           preferences.appendChild(preference);
+
+          if (!("setElementValue" in preference)) {
+            await new Promise((resolve) => {
+              preference.addEventListener("bindingattached", resolve, { once: true });
+            });
+          }
         }
 
         if (!prefs[i].element)
           continue;
 
         var element = document.getElementById(prefs[i].element);
         if (element) {
           // Make sure we have the font list ready for readFontSelection below to
@@ -131,17 +137,20 @@ var gDisplayPane = {
     if (!preference) {
       preference = document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul", "preference");
       preference.id = defaultFontTypePref;
       preference.type = "string";
       preference.name = defaultFontTypePref;
       preference.setAttribute("onchange", "gDisplayPane._rebuildFonts();");
       document.getElementById("displayPreferences").appendChild(preference);
     }
-    return preference.value;
+
+    // We should return preference.value here, but we can't wait for the binding to load,
+    // or things get really messy. Fortunately this will give the same answer.
+    return Services.prefs.getCharPref(defaultFontTypePref);
   },
 
   /**
    * Determine the appropriate value to select for defaultFont, for the
    * following cases:
    * - there is no setting
    * - the font selected by the user is no longer present (e.g. deleted from
    *   fonts folder)
--- a/mail/components/preferences/jar.mn
+++ b/mail/components/preferences/jar.mn
@@ -1,15 +1,14 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 messenger.jar:
 *   content/messenger/preferences/aboutPreferences.xul
-    content/messenger/preferences/aboutPreferences.xml
     content/messenger/preferences/preferences.css
     content/messenger/preferences/preferences.js
 *   content/messenger/preferences/preferences.xml       (../../../common/bindings/preferences.xml)
     content/messenger/preferences/preferencesTab.js
     content/messenger/preferences/general.js
 #ifdef XP_MACOSX
     content/messenger/preferences/dockoptions.xul
 #endif
--- a/mail/components/preferences/preferences.css
+++ b/mail/components/preferences/preferences.css
@@ -1,15 +1,14 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 prefwindow,
 prefwindow:root /* override :root */ {
-  -moz-binding: url("chrome://messenger/content/preferences/preferences.xml#prefwindow");
   -moz-box-orient: vertical;
 }
 
 prefpane {
   -moz-binding: url("chrome://messenger/content/preferences/preferences.xml#prefpane");
   -moz-box-orient: vertical;
 }
 
--- a/mail/components/preferences/preferences.js
+++ b/mail/components/preferences/preferences.js
@@ -2,89 +2,140 @@
  * 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/. */
 
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
 ChromeUtils.import("resource:///modules/MailServices.jsm");
 ChromeUtils.import("resource:///modules/ExtensionSupport.jsm");
 
-window.addEventListener("load", function() {
-  let prefWindow = document.getElementById("MailPreferences");
-  if (!Services.prefs.getBoolPref("mail.chat.enabled")) {
-    let radio =
-      document.getAnonymousElementByAttribute(prefWindow, "pane", "paneChat");
-    if (radio.selected)
-      prefWindow.showPane(document.getElementById("paneGeneral"));
-    radio.hidden = true;
-  }
-  if (!ExtensionSupport.loadedLegacyExtensions.has("{e2fda1a4-762b-4020-b5ad-a41df1933103}")) {
-    let radio =
-      document.getAnonymousElementByAttribute(prefWindow, "pane", "paneLightning");
-    if (radio.selected)
-      prefWindow.showPane(document.getElementById("paneGeneral"));
-    radio.hidden = true;
+var paneDeck = document.getElementById("paneDeck");
+var prefPanes = [...document.getElementsByTagName("prefpane")];
+var selector = document.getElementById("selector");
+
+(function() {
+  for (let pane of prefPanes) {
+    if (pane.id == "paneChat" && !Services.prefs.getBoolPref("mail.chat.enabled")) {
+      continue;
+    }
+    if (pane.id == "paneLightning" &&
+        !ExtensionSupport.loadedLegacyExtensions.has("{e2fda1a4-762b-4020-b5ad-a41df1933103}")) {
+      continue;
+    }
+
+    var radio = document.createElement("radio");
+    radio.setAttribute("pane", pane.id);
+    radio.setAttribute("value", pane.id);
+    radio.setAttribute("label", pane.label);
+    radio.setAttribute("oncommand", `showPane("${pane.id}");`);
+    // Expose preference group choice to accessibility APIs as an unchecked list item
+    // The parent group is exposed to accessibility APIs as a list
+    if (pane.image) {
+      radio.setAttribute("src", pane.image);
+    }
+    radio.style.listStyleImage = pane.style.listStyleImage;
+    selector.appendChild(radio);
+
+    pane.dispatchEvent(new CustomEvent("paneload"));
+    new Function(pane.getAttribute("onpaneload")).call(pane);
   }
 
-  let categories = prefWindow._selector;
+  if (prefPanes.length == 1) {
+    selector.setAttribute("collapsed", "true");
+  }
+
+  window.addEventListener("DOMContentLoaded", function() {
+    if (document.documentElement.hasAttribute("lastSelected")) {
+      showPane(document.documentElement.getAttribute("lastSelected"));
+    } else {
+      showPane(prefPanes[0].id);
+    }
+  });
+
   document.documentElement.addEventListener("keydown", function(event) {
     if (event.keyCode == KeyEvent.DOM_VK_TAB ||
         event.keyCode == KeyEvent.DOM_VK_UP ||
         event.keyCode == KeyEvent.DOM_VK_DOWN ||
         event.keyCode == KeyEvent.DOM_VK_LEFT ||
         event.keyCode == KeyEvent.DOM_VK_RIGHT) {
-      categories.setAttribute("keyboard-navigation", "true");
+      selector.setAttribute("keyboard-navigation", "true");
     }
   });
-  categories.addEventListener("mousedown", function() {
+  selector.addEventListener("mousedown", function() {
     this.removeAttribute("keyboard-navigation");
   });
-});
+})();
+
+/**
+ * Actually switches to the specified pane, fires events, and remembers the pane.
+ *
+ * @param paneID ID of the prefpane to select
+ */
+function showPane(paneID) {
+  if (!paneID) {
+    return;
+  }
+
+  let pane = document.getElementById(paneID);
+  if (!pane) {
+    return;
+  }
+
+  selector.value = paneID;
+  paneDeck.selectedPanel = pane;
+  pane.dispatchEvent(new CustomEvent("paneSelected", { bubbles: true }));
+
+  document.documentElement.setAttribute("lastSelected", paneID);
+  Services.xulStore.persist(document.documentElement, "lastSelected");
+}
 
 /**
  * Selects the specified preferences pane
  *
- * @param prefWindow    the prefwindow element to operate on
- * @param aPaneID       ID of prefpane to select
- * @param aTabID        ID of tab to select on the prefpane
- * @param aSubdialogID  ID of button to activate, opening a subdialog
+ * @param prefWindow          the prefwindow element to operate on
+ * @param paneID              ID of prefpane to select
+ * @param tabID               ID of tab to select on the prefpane
+ * @param otherArgs.subdialog ID of button to activate, opening a subdialog
  */
-function selectPaneAndTab(prefWindow, aPaneID, aTabID, aSubdialogID) {
-  if (aPaneID) {
-    let prefPane = document.getElementById(aPaneID);
+function selectPaneAndTab(prefWindow, paneID, tabID, otherArgs) {
+  if (paneID) {
+    let prefPane = document.getElementById(paneID);
     let tabOnEvent = false;
     // The prefwindow element selects the pane specified in window.arguments[0]
     // automatically. But let's check it and if the prefs window was already
     // open, the current prefpane may not be the wanted one.
-    if (prefWindow.currentPane.id != prefPane.id) {
-      if (aTabID && !prefPane.loaded) {
+    if (getCurrentPaneID() != prefPane.id) {
+      if (tabID && !prefPane.loaded) {
         prefPane.addEventListener("paneload", function() {
-          showTab(prefPane, aTabID);
+          showTab(prefPane, tabID);
         }, {once: true});
         tabOnEvent = true;
       }
-      prefWindow.showPane(prefPane);
+      showPane(prefPane.id);
     }
-    if (aTabID && !tabOnEvent)
-      showTab(prefPane, aTabID, aSubdialogID);
+    if (tabID && !tabOnEvent) {
+      showTab(prefPane, tabID, otherArgs ? otherArgs.subdialog : undefined);
+    }
   }
 }
 
 /**
  * Select the specified tab
  *
- * @param aPane         prefpane to operate on
- * @param aTabID        ID of tab to select on the prefpane
- * @param aSubdialogID  ID of button to activate, opening a subdialog
+ * @param pane         prefpane to operate on
+ * @param tabID        ID of tab to select on the prefpane
+ * @param subdialogID  ID of button to activate, opening a subdialog
  */
-function showTab(aPane, aTabID, aSubdialogID) {
-  aPane.querySelector("tabbox").selectedTab = document.getElementById(aTabID);
-  if (aSubdialogID)
-    setTimeout(function() { document.getElementById(aSubdialogID).click(); }, 0);
+function showTab(pane, tabID, subdialogID) {
+  pane.querySelector("tabbox").selectedTab = document.getElementById(tabID);
+  if (subdialogID) {
+    setTimeout(function() {
+      document.getElementById(subdialogID).click();
+    });
+  }
 }
 
 /**
  * Get the ID of the current pane.
  */
 function getCurrentPaneID() {
-  let prefWindow = document.getElementById("MailPreferences");
-  return prefWindow.currentPane ? prefWindow.currentPane.id : null;
+  return paneDeck.selectedPanel.id;
 }
--- a/mail/components/preferences/subdialogs.js
+++ b/mail/components/preferences/subdialogs.js
@@ -524,20 +524,18 @@ var gSubDialog = {
   _dialogTemplate: null,
   _nextDialogID: 0,
   _preloadDialog: null,
   get _topDialog() {
     return this._dialogs.length > 0 ? this._dialogs[this._dialogs.length - 1] : undefined;
   },
 
   init() {
-    this._dialogStack = document.getAnonymousElementByAttribute(
-      top.document.documentElement, "id", "dialogStack");
-    this._dialogTemplate = document.getAnonymousElementByAttribute(
-      top.document.documentElement, "id", "dialogTemplate");
+    this._dialogStack = document.getElementById("dialogStack");
+    this._dialogTemplate = document.getElementById("dialogTemplate");
     this._preloadDialog = new SubDialog({template: this._dialogTemplate,
                                          parentElement: this._dialogStack,
                                          id: this._nextDialogID++});
   },
 
   open(aURL, aFeatures = null, aParams = null, aClosingCallback = null) {
     // If we're already open/opening on this URL, do nothing.
     if (this._topDialog && this._topDialog._openedURL == aURL) {
--- a/mail/test/mozmill/pref-window/test-font-chooser.js
+++ b/mail/test/mozmill/pref-window/test-font-chooser.js
@@ -93,19 +93,17 @@ function _verify_fonts_displayed(aDefaul
   mc.waitFor(() => displayPaneActual.itemCount > 0,
                 "No font names were populated in the font picker.");
   assert_fonts_equal("display pane", displayPaneExpected, displayPaneActual.value);
 
   // Now open the advanced dialog.
   mc.click(content_tab_eid(prefTab, "advancedFonts"));
   let fontc = wait_for_frame_load(
     prefTab.browser.contentDocument
-           .getAnonymousElementByAttribute(
-             prefTab.browser.contentDocument.documentElement, "id",
-             "dialogOverlay-0")
+           .getElementById("dialogOverlay-0")
            .querySelector("browser"),
     "chrome://messenger/content/preferences/fonts.xul"
   );
 
   // The font pickers are populated async so we need to wait for it.
   for (let fontElemId of ["serif", "sans-serif", "monospace"]) {
     fontc.waitFor(() => fontc.e(fontElemId).label != "",
                   "Timeout waiting for font picker '" + fontElemId + "' to populate.");
--- a/mail/test/mozmill/shared-modules/test-pref-window-helpers.js
+++ b/mail/test/mozmill/shared-modules/test-pref-window-helpers.js
@@ -38,17 +38,17 @@ function installInto(module) {
  * be one of the prefpane ids in mail/components/preferences/aboutPreferences.xul.
  *
  * @param aPaneID The ID of the pref pane to display (see
  *     mail/components/preferences/aboutPreferences.xul for valid IDs.)
  */
 function open_pref_tab(aPaneID) {
   let tab = cth.open_content_tab_with_click(function() { fdh.mc.window.openOptionsDialog(aPaneID) },
                                             "about:preferences", fdh.mc, "preferencesTab");
-  utils.waitFor(() => tab.browser.contentDocument.documentElement.currentPane.id == aPaneID,
+  utils.waitFor(() => tab.browser.contentWindow.getCurrentPaneID() == aPaneID,
                 "Timed out waiting for prefpane " + aPaneID + " to load.");
   return tab;
 }
 
 /**
  * Close the preferences tab.
  *
  * @param aTab  The content tab to close.
--- a/mail/themes/linux/mail/preferences/aboutPreferences.css
+++ b/mail/themes/linux/mail/preferences/aboutPreferences.css
@@ -1,16 +1,16 @@
 /* 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 url("chrome://messenger/skin/shared/in-content/aboutPreferences.css");
 
 .dialogBox,
-#MailPreferences > prefpane {
+#MailPreferences prefpane {
   font-size: 1.11em;
 }
 
 radio[pane] > .radio-label-box {
   font-size: 1.2em;
 }
 
 checkbox {
--- a/mail/themes/linux/mail/preferences/preferences.css
+++ b/mail/themes/linux/mail/preferences/preferences.css
@@ -61,21 +61,17 @@ menulist > .menulist-label-box > .menuli
   margin-inline-end: 5px;
 }
 
 menulist > menupopup > menuitem > .menu-iconic-left {
   margin-inline-end: 5px !important;
 }
 
 /* Attachments Pane */
-#MailPreferences[animated="true"] #handlersView {
-  height: 25em;
-}
-
-#MailPreferences[animated="false"] #handlersView {
+#handlersView {
   -moz-box-flex: 1;
 }
 
 /* Modeless Window Dialogs */
 .windowDialog,
 .windowDialog prefpane {
   padding: 0px;
 }
--- a/mail/themes/osx/mail/preferences/aboutPreferences.css
+++ b/mail/themes/osx/mail/preferences/aboutPreferences.css
@@ -1,17 +1,17 @@
 /* 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 url("chrome://messenger/skin/shared/in-content/aboutPreferences.css");
 @namespace html "http://www.w3.org/1999/xhtml";
 
 .dialogBox,
-#MailPreferences > prefpane {
+#MailPreferences prefpane {
   font-size: 1.36em;
 }
 
 radio[pane] > .radio-label-box {
   font-size: 1.46em;
 }
 
 radio[pane][focused="true"] > .radio-check {
--- a/mail/themes/osx/mail/preferences/preferences.css
+++ b/mail/themes/osx/mail/preferences/preferences.css
@@ -55,21 +55,17 @@ menulist > menupopup > menuitem {
   font: -moz-pull-down-menu;
 }
 
 prefwindow:not([type="child"]) {
   padding: 0 !important;
 }
 
 /* Attachments Pane */
-#MailPreferences[animated="true"] #handlersView {
-  height: 17em;
-}
-
-#MailPreferences[animated="false"] #handlersView {
+#handlersView {
   -moz-box-flex: 1;
 }
 
 #browserStartupHomepage {
   padding-top: 2px;
   padding-bottom: 3px;
   padding-inline-start: 4px;
   padding-inline-end: 2px;
--- a/mail/themes/shared/mail/incontentprefs/aboutPreferences.css
+++ b/mail/themes/shared/mail/incontentprefs/aboutPreferences.css
@@ -30,17 +30,17 @@ html|h2 {
   margin: 4px 0 !important;
 }
 
 #preferencesContainer {
   padding: 40px 28px;
   overflow: auto;
 }
 
-#MailPreferences > prefpane {
+#MailPreferences prefpane {
   max-width: 800px;
   padding: 0;
 }
 
 tabpanel > label,
 tabpanel > description,
 tabpanel > hbox > description {
   margin-inline-start: 0;
--- a/mail/themes/windows/mail/preferences/aboutPreferences.css
+++ b/mail/themes/windows/mail/preferences/aboutPreferences.css
@@ -1,17 +1,17 @@
 /* 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 url("chrome://messenger/skin/shared/in-content/aboutPreferences.css");
 @namespace html "http://www.w3.org/1999/xhtml";
 
 .dialogBox,
-#MailPreferences > prefpane {
+#MailPreferences prefpane {
   font-size: 1.25em;
 }
 
 radio[pane] > .radio-label-box {
   font-size: 1.34em;
 }
 
 .actionsMenu > .menulist-label-box > .menulist-icon {
--- a/mail/themes/windows/mail/preferences/preferences.css
+++ b/mail/themes/windows/mail/preferences/preferences.css
@@ -54,21 +54,17 @@ prefwindow[type="child"] .prefWindow-dlg
 @media (-moz-windows-default-theme) {
   menulist > .menulist-label-box > .menulist-icon[src] {
     margin-inline-start: 7px;
     margin-inline-end: 10px;
   }
 }
 
 /* Attachments Pane */
-#MailPreferences[animated="true"] #handlersView {
-  height: 25em;
-}
-
-#MailPreferences[animated="false"] #handlersView {
+#handlersView {
   -moz-box-flex: 1;
 }
 
 /* Modeless Window Dialogs */
 .windowDialog,
 .windowDialog prefpane {
   padding: 0px;
 }