Bug 731041 - Tidy up addon inline preferences code, toolkit; r=mbrubeck, Unfocused
authorGeoff Lankow <geoff@darktrojan.net>
Wed, 07 Mar 2012 00:41:25 +1300
changeset 88373 6faa3058142b7afddb262daf5b5cfc112938c6d8
parent 88372 074a6a85dab687190c0100d8bb90fecfb86d1ddc
child 88374 87d12a41e3e0beaeb5a52de6cec9b3421be8d329
push id22194
push usermak77@bonardo.net
push dateWed, 07 Mar 2012 09:33:54 +0000
treeherdermozilla-central@8ef88a69f861 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmbrubeck, Unfocused
bugs731041
milestone13.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 731041 - Tidy up addon inline preferences code, toolkit; r=mbrubeck, Unfocused
toolkit/mozapps/extensions/content/extensions.js
toolkit/mozapps/extensions/content/setting.xml
toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1/options.xul
toolkit/mozapps/extensions/test/browser/browser_inlinesettings.js
toolkit/themes/gnomestripe/mozapps/extensions/extensions.css
toolkit/themes/pinstripe/mozapps/extensions/extensions.css
toolkit/themes/winstripe/mozapps/extensions/extensions.css
--- a/toolkit/mozapps/extensions/content/extensions.js
+++ b/toolkit/mozapps/extensions/content/extensions.js
@@ -2877,50 +2877,34 @@ var gDetailView = {
 
     var xml = xhr.responseXML;
     var settings = xml.querySelectorAll(":root > setting");
 
     var firstSetting = null;
     for (var i = 0; i < settings.length; i++) {
       var setting = settings[i];
 
-      // Remove setting description, for replacement later
       var desc = stripTextNodes(setting).trim();
-      if (setting.hasAttribute("desc")) {
-        desc = setting.getAttribute("desc").trim();
-        setting.removeAttribute("desc");
-      }
+      if (!setting.hasAttribute("desc"))
+        setting.setAttribute("desc", desc);
 
       var type = setting.getAttribute("type");
       if (type == "file" || type == "directory")
         setting.setAttribute("fullpath", "true");
 
       rows.appendChild(setting);
       var visible = window.getComputedStyle(setting, null).getPropertyValue("display") != "none";
       if (!firstSetting && visible) {
         setting.setAttribute("first-row", true);
         firstSetting = setting;
       }
-
-      // Add a new row containing the description
-      if (desc) {
-        var row = document.createElement("row");
-        if (!visible) {
-          row.setAttribute("unsupported", "true");
-        }
-        var label = document.createElement("label");
-        label.className = "preferences-description";
-        label.textContent = desc;
-        row.appendChild(label);
-        rows.appendChild(row);
-      }
     }
 
-	// Ensure the page has loaded and force the XBL bindings to be synchronously applied,
-	// then notify observers.
+    // Ensure the page has loaded and force the XBL bindings to be synchronously applied,
+    // then notify observers.
     if (gViewController.viewPort.selectedPanel.hasAttribute("loading")) {
       gDetailView.node.addEventListener("ViewChanged", function viewChangedEventListener() {
         gDetailView.node.removeEventListener("ViewChanged", viewChangedEventListener, false);
         if (firstSetting)
           firstSetting.clientTop;
         Services.obs.notifyObservers(document, "addon-options-displayed", gDetailView._addon.id);
         if (aScrollToPreferences)
           gDetailView.scrollToPreferencesRows();
--- a/toolkit/mozapps/extensions/content/setting.xml
+++ b/toolkit/mozapps/extensions/content/setting.xml
@@ -46,17 +46,17 @@
 <bindings xmlns="http://www.mozilla.org/xbl"
           xmlns:xbl="http://www.mozilla.org/xbl"
           xmlns:html="http://www.w3.org/1999/xhtml"
           xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
 
   <binding id="settings">
     <content orient="vertical">
       <xul:label class="settings-title" xbl:inherits="xbl:text=label" flex="1"/>
-      <children />
+      <children/>
     </content>
   </binding>
 
   <binding id="setting-base">
     <implementation>
       <constructor><![CDATA[
         this.preferenceChanged();
         
@@ -155,33 +155,32 @@
 
       <property name="usePref" readonly="true" onget="return this.hasAttribute('pref');"/>
       <property name="pref" readonly="true" onget="return this.getAttribute('pref');"/>
       <property name="type" readonly="true" onget="return this.getAttribute('type');"/>
       <property name="value" onget="return this.input.value;" onset="return this.input.value = val;"/>
 
       <field name="_updatingInput">false</field>
       <field name="input">document.getAnonymousElementByAttribute(this, "anonid", "input");</field>
-
       <field name="settings">
         this.parentNode.localName == "settings" ? this.parentNode : null;
       </field>
     </implementation>
   </binding>
 
   <binding id="setting-bool" extends="chrome://mozapps/content/extensions/setting.xml#setting-base">
     <content>
-      <xul:vbox class="setting-label">
-        <xul:label class="preferences-title" xbl:inherits="xbl:text=title" flex="1"/>
-        <xul:label class="preferences-description" xbl:inherits="xbl:text=desc" flex="1">
-          <children/>
-        </xul:label>
+      <xul:vbox>
+        <xul:hbox class="preferences-alignment">
+          <xul:label class="preferences-title" flex="1" xbl:inherits="xbl:text=title"/>
+        </xul:hbox>
+        <xul:description class="preferences-description" flex="1" xbl:inherits="xbl:text=desc"/>
       </xul:vbox>
-      <xul:hbox anonid="input-container" class="setting-input">
-        <xul:checkbox anonid="input" xbl:inherits="disabled,onlabel,offlabel" oncommand="inputChanged();"/>
+      <xul:hbox class="preferences-alignment">
+        <xul:checkbox anonid="input" xbl:inherits="disabled,onlabel,offlabel,label=checkboxlabel" oncommand="inputChanged();"/>
       </xul:hbox>
     </content>
 
     <implementation>
       <method name="valueFromPreference">
         <body>
         <![CDATA[
           let val = Services.prefs.getBoolPref(this.pref);
@@ -199,29 +198,17 @@
         </body>
       </method>
 
       <property name="value" onget="return this.input.checked;" onset="return this.input.setChecked(val);"/>
       <property name="inverted" readonly="true" onget="return this.getAttribute('inverted');"/>
     </implementation>
   </binding>
 
-  <binding id="setting-boolint" extends="chrome://mozapps/content/extensions/setting.xml#setting-base">
-    <content>
-      <xul:vbox class="setting-label">
-        <xul:label class="preferences-title" xbl:inherits="xbl:text=title" flex="1"/>
-        <xul:label class="preferences-description" xbl:inherits="xbl:text=desc" flex="1">
-          <children/>
-        </xul:label>
-      </xul:vbox>
-      <xul:hbox anonid="input-container" class="setting-input">
-        <xul:checkbox anonid="input" xbl:inherits="disabled" oncommand="inputChanged();"/>
-      </xul:hbox>
-    </content>
-
+  <binding id="setting-boolint" extends="chrome://mozapps/content/extensions/setting.xml#setting-bool">
     <implementation>
       <method name="valueFromPreference">
         <body>
         <![CDATA[
           let val = Services.prefs.getIntPref(this.pref);
           this.value = (val == this.getAttribute("on"));
          ]]>
         </body>
@@ -229,19 +216,16 @@
 
       <method name="valueToPreference">
         <body>
         <![CDATA[
           Services.prefs.setIntPref(this.pref, this.getAttribute(this.value ? "on" : "off"));
         ]]>
         </body>
       </method>
-
-      <property name="value" onget="return this.input.checked;" onset="return this.input.setChecked(val);"/>
-      <property name="inverted" readonly="true" onget="return this.getAttribute('inverted');"/>
     </implementation>
   </binding>
 
   <binding id="setting-localized-bool" extends="chrome://mozapps/content/extensions/setting.xml#setting-bool">
     <implementation>
       <method name="valueFromPreference">
         <body>
         <![CDATA[
@@ -258,30 +242,30 @@
           let val = this.value;
           if(this.inverted) val = !val;
           let pref = Components.classes["@mozilla.org/pref-localizedstring;1"].createInstance(Components.interfaces.nsIPrefLocalizedString);
           pref.data = this.inverted ? (!val).toString() : val.toString();
           Services.prefs.setComplexValue(this.pref, Components.interfaces.nsIPrefLocalizedString, pref);
         ]]>
         </body>
       </method>
-
     </implementation>
   </binding>
 
   <binding id="setting-integer" extends="chrome://mozapps/content/extensions/setting.xml#setting-base">
     <content>
-      <xul:vbox class="setting-label">
-        <xul:label class="preferences-title" xbl:inherits="xbl:text=title" flex="1"/>
-        <xul:label class="preferences-description" xbl:inherits="xbl:text=desc" flex="1">
-          <children/>
-        </xul:label>
+      <xul:vbox>
+        <xul:hbox class="preferences-alignment">
+          <xul:label class="preferences-title" flex="1" xbl:inherits="xbl:text=title"/>
+        </xul:hbox>
+        <xul:description class="preferences-description" flex="1" xbl:inherits="xbl:text=desc"/>
       </xul:vbox>
-      <xul:hbox anonid="input-container" class="setting-input">
-        <xul:textbox type="number" anonid="input" xbl:inherits="disabled,emptytext,min,max,increment,hidespinbuttons,wraparound" oninput="inputChanged();" onchange="inputChanged();"/>
+      <xul:hbox class="preferences-alignment">
+        <xul:textbox type="number" anonid="input" flex="1" oninput="inputChanged();" onchange="inputChanged();"
+                     xbl:inherits="disabled,emptytext,min,max,increment,hidespinbuttons,wraparound"/>
       </xul:hbox>
     </content>
 
     <implementation>
       <method name="valueFromPreference">
         <body>
         <![CDATA[
           let val = Services.prefs.getIntPref(this.pref);
@@ -292,46 +276,44 @@
 
       <method name="valueToPreference">
         <body>
         <![CDATA[
           Services.prefs.setIntPref(this.pref, this.value);
         ]]>
         </body>
       </method>
-
-      <property name="type" readonly="true" onget="return this.getAttribute('type');"/>
-      <property name="value" onget="return this.input.value;" onset="return this.input.value = val;"/>
     </implementation>
   </binding>
 
   <binding id="setting-control" extends="chrome://mozapps/content/extensions/setting.xml#setting-base">
     <content>
-      <xul:vbox class="setting-label">
-        <xul:label class="preferences-title" xbl:inherits="xbl:text=title" flex="1"/>
-        <xul:label class="preferences-description" xbl:inherits="xbl:text=desc" flex="1">
-          <children/>
-        </xul:label>
+      <xul:vbox>
+        <xul:hbox class="preferences-alignment">
+          <xul:label class="preferences-title" flex="1" xbl:inherits="xbl:text=title"/>
+        </xul:hbox>
+        <xul:description class="preferences-description" flex="1" xbl:inherits="xbl:text=desc"/>
       </xul:vbox>
-      <xul:hbox anonid="input-container" class="setting-input">
+      <xul:hbox class="preferences-alignment">
         <children includes="button|menulist"/>
       </xul:hbox>
     </content>
   </binding>
 
   <binding id="setting-string" extends="chrome://mozapps/content/extensions/setting.xml#setting-base">
     <content>
-      <xul:vbox class="setting-label">
-        <xul:label class="preferences-title" xbl:inherits="xbl:text=title" flex="1"/>
-        <xul:label class="preferences-description" xbl:inherits="xbl:text=desc" flex="1">
-          <children/>
-        </xul:label>
+      <xul:vbox>
+        <xul:hbox class="preferences-alignment">
+          <xul:label class="preferences-title" flex="1" xbl:inherits="xbl:text=title"/>
+        </xul:hbox>
+        <xul:description class="preferences-description" flex="1" xbl:inherits="xbl:text=desc"/>
       </xul:vbox>
-      <xul:hbox anonid="input-container" class="setting-input">
-        <xul:textbox xbl:inherits="disabled,emptytext,type=inputtype,min,max,increment,hidespinbuttons,decimalplaces,wraparound" anonid="input" oninput="inputChanged();"/>
+      <xul:hbox class="preferences-alignment">
+        <xul:textbox anonid="input" flex="1" oninput="inputChanged();"
+                     xbl:inherits="disabled,emptytext,type=inputtype,min,max,increment,hidespinbuttons,decimalplaces,wraparound"/>
       </xul:hbox>
     </content>
 
     <implementation>
       <method name="valueFromPreference">
         <body>
         <![CDATA[
           const nsISupportsString = Components.interfaces.nsISupportsString;
@@ -345,30 +327,28 @@
         <![CDATA[
           const nsISupportsString = Components.interfaces.nsISupportsString;
           let iss = Components.classes["@mozilla.org/supports-string;1"].createInstance(nsISupportsString);
           iss.data = this.value;
           Services.prefs.setComplexValue(this.pref, nsISupportsString, iss);
         ]]>
         </body>
       </method>
-
-      <property name="value" onget="return this.input.value;" onset="return this.input.value=val;"/>
     </implementation>
   </binding>
 
   <binding id="setting-color" extends="chrome://mozapps/content/extensions/setting.xml#setting-base">
     <content>
-      <xul:vbox class="setting-label">
-        <xul:label class="preferences-title" xbl:inherits="xbl:text=title" flex="1"/>
-        <xul:label class="preferences-description" xbl:inherits="xbl:text=desc" flex="1">
-          <children/>
-        </xul:label>
+      <xul:vbox>
+        <xul:hbox class="preferences-alignment">
+          <xul:label class="preferences-title" flex="1" xbl:inherits="xbl:text=title"/>
+        </xul:hbox>
+        <xul:description class="preferences-description" flex="1" xbl:inherits="xbl:text=desc"/>
       </xul:vbox>
-      <xul:hbox anonid="input-container" class="setting-input">
+      <xul:hbox class="preferences-alignment">
         <xul:colorpicker type="button" anonid="input" xbl:inherits="disabled" onchange="document.getBindingParent(this).inputChanged();"/>
       </xul:hbox>
     </content>
 
     <implementation>
       <method name="valueFromPreference">
         <body>
         <![CDATA[
@@ -389,25 +369,25 @@
       </method>
 
       <property name="value" onget="return this.input.color;" onset="return this.input.color = val;"/>
     </implementation>
   </binding>
 
   <binding id="setting-path" extends="chrome://mozapps/content/extensions/setting.xml#setting-base">
     <content>
-      <xul:vbox class="setting-label">
-        <xul:label class="preferences-title" xbl:inherits="xbl:text=title" flex="1"/>
-        <xul:label class="preferences-description" xbl:inherits="xbl:text=desc" flex="1">
-          <children/>
-        </xul:label>
+      <xul:vbox>
+        <xul:hbox class="preferences-alignment">
+          <xul:label class="preferences-title" flex="1" xbl:inherits="xbl:text=title"/>
+        </xul:hbox>
+        <xul:description class="preferences-description" flex="1" xbl:inherits="xbl:text=desc"/>
       </xul:vbox>
-      <xul:hbox anonid="input-container" align="center" class="setting-input">
-        <xul:button type="button" anonid="button" label="&settings.path.button.label;" xbl:inherits="disabled" oncommand="showPicker();" />
-        <xul:label anonid="input" flex="1" crop="center" xbl:inherits="disabled" />
+      <xul:hbox class="preferences-alignment">
+        <xul:button type="button" anonid="button" label="&settings.path.button.label;" xbl:inherits="disabled" oncommand="showPicker();"/>
+        <xul:label anonid="input" flex="1" crop="center" xbl:inherits="disabled"/>
       </xul:hbox>
     </content>
 
     <implementation>
       <method name="showPicker">
         <body>
         <![CDATA[
           var filePicker = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
@@ -471,24 +451,24 @@
        ]]>
         </setter>
       </property>
     </implementation>
   </binding>
 
   <binding id="setting-multi" extends="chrome://mozapps/content/extensions/setting.xml#setting-base">
     <content>
-      <xul:vbox class="setting-label">
-        <xul:label class="preferences-title" xbl:inherits="xbl:text=title" flex="1"/>
-        <xul:label class="preferences-description" xbl:inherits="xbl:text=desc" flex="1">
-          <children/>
-        </xul:label>
+      <xul:vbox>
+        <xul:hbox class="preferences-alignment">
+          <xul:label class="preferences-title" flex="1" xbl:inherits="xbl:text=title"/>
+        </xul:hbox>
+        <xul:description class="preferences-description" flex="1" xbl:inherits="xbl:text=desc"/>
       </xul:vbox>
-      <xul:hbox class="setting-input">
-        <children includes="radiogroup|menulist" />
+      <xul:hbox class="preferences-alignment">
+        <children includes="radiogroup|menulist"/>
       </xul:hbox>
     </content>
 
     <implementation>
       <constructor>
       <![CDATA[
         this.control.addEventListener("command", this.valueToPreference.bind(this), false);
       ]]>
--- a/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1/options.xul
+++ b/toolkit/mozapps/extensions/test/browser/addons/browser_inlinesettings1/options.xul
@@ -1,11 +1,11 @@
 <?xml version="1.0" ?>
 <vbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
-  <setting pref="extensions.inlinesettings1.bool" type="bool" title="Bool"/>
+  <setting pref="extensions.inlinesettings1.bool" type="bool" title="Bool" checkboxlabel="Check box label"/>
   <setting pref="extensions.inlinesettings1.boolint" type="boolint" on="1" off="2" title="BoolInt"/>
   <setting pref="extensions.inlinesettings1.integer" type="integer" title="Integer"/>
   <setting pref="extensions.inlinesettings1.string" type="string" title="String"/>
   <setting type="control" title="Menulist">
     <menulist sizetopopup="always" oncommand="window._testValue = this.value;">
       <menupopup>
         <menuitem label="Alpha" value="1" />
         <menuitem label="Bravo" value="2" />
--- a/toolkit/mozapps/extensions/test/browser/browser_inlinesettings.js
+++ b/toolkit/mozapps/extensions/test/browser/browser_inlinesettings.js
@@ -16,17 +16,17 @@ MockFilePicker.init();
 var observer = {
   lastData: null,
   observe: function(aSubject, aTopic, aData) {
     if (aTopic == "addon-options-displayed") {
       this.lastData = aData;
       // Test if the binding has applied before the observers are notified. We test the second setting here,
       // because the code operates on the first setting and we want to check it applies to all.
       var setting = aSubject.querySelector("rows > setting[first-row] ~ setting");
-      var input = gManagerWindow.document.getAnonymousElementByAttribute(setting, "class", "setting-label");
+      var input = gManagerWindow.document.getAnonymousElementByAttribute(setting, "class", "preferences-title");
       isnot(input, null, "XBL binding should be applied");
 
       // Add some extra height to the scrolling pane to ensure that it needs to scroll when appropriate.
       gManagerWindow.document.getElementById("detail-controls").style.marginBottom = "1000px";
     }
   }
 };
 
@@ -169,16 +169,17 @@ add_test(function() {
     var grid = gManagerWindow.document.getElementById("detail-grid");
     var settings = grid.querySelectorAll("rows > setting");
     is(settings.length, SETTINGS_ROWS, "Grid should have settings children");
 
     ok(settings[0].hasAttribute("first-row"), "First visible row should have first-row attribute");
     Services.prefs.setBoolPref("extensions.inlinesettings1.bool", false);
     var input = gManagerWindow.document.getAnonymousElementByAttribute(settings[0], "anonid", "input");
     isnot(input.checked, true, "Checkbox should have initial value");
+    is(input.label, "Check box label", "Checkbox should be labelled");
     EventUtils.synthesizeMouseAtCenter(input, { clickCount: 1 }, gManagerWindow);
     is(input.checked, true, "Checkbox should have updated value");
     is(Services.prefs.getBoolPref("extensions.inlinesettings1.bool"), true, "Bool pref should have been updated");
     EventUtils.synthesizeMouseAtCenter(input, { clickCount: 1 }, gManagerWindow);
     isnot(input.checked, true, "Checkbox should have updated value");
     is(Services.prefs.getBoolPref("extensions.inlinesettings1.bool"), false, "Bool pref should have been updated");
 
     ok(!settings[1].hasAttribute("first-row"), "Not the first row");
@@ -376,55 +377,36 @@ add_test(function() {
     node = settings[0];
     is_element_hidden(node, "Unsupported settings should not be visible");
     ok(!node.hasAttribute("first-row"), "Hidden row is not the first row");
 
     node = settings[1];
     is(node.nodeName, "setting", "Should be a setting node");
     ok(node.hasAttribute("first-row"), "First visible row should have first-row attribute");
     var description = gManagerWindow.document.getAnonymousElementByAttribute(node, "class", "preferences-description");
-    is(description.textContent.trim(), "", "Description node should be empty");
-
-    node = node.nextSibling;
-    is(node.nodeName, "row", "Setting should be followed by a row node");
-    is_element_visible(node, "Description should be visible");
-    is(node.textContent, "Description Attribute", "Description should be in this row");
+    is(description.textContent, "Description Attribute", "Description node should contain description");
 
     node = settings[2];
     is(node.nodeName, "setting", "Should be a setting node");
     ok(!node.hasAttribute("first-row"), "Not the first row");
     description = gManagerWindow.document.getAnonymousElementByAttribute(node, "class", "preferences-description");
-    is(description.textContent.trim(), "", "Description node should be empty");
-
-    node = node.nextSibling;
-    is(node.nodeName, "row", "Setting should be followed by a row node");
-    is_element_visible(node, "Description should be visible");
-    is(node.textContent, "Description Text Node", "Description should be in this row");
+    is(description.textContent, "Description Text Node", "Description node should contain description");
 
     node = settings[3];
     is(node.nodeName, "setting", "Should be a setting node");
     ok(!node.hasAttribute("first-row"), "Not the first row");
     description = gManagerWindow.document.getAnonymousElementByAttribute(node, "class", "preferences-description");
-    is(description.textContent.trim(), "", "Description node should be empty");
+    is(description.textContent, "This is a test, all this text should be visible", "Description node should contain description");
     var button = node.firstElementChild;
     isnot(button, null, "There should be a button");
 
-    node = node.nextSibling;
-    is(node.nodeName, "row", "Setting should be followed by a row node");
-    is_element_visible(node, "Description should be visible");
-    is(node.textContent.trim(), "This is a test, all this text should be visible", "Description should be in this row");
-
     node = settings[4];
     is_element_hidden(node, "Unsupported settings should not be visible");
     ok(!node.hasAttribute("first-row"), "Hidden row is not the first row");
 
-    node = node.nextSibling;
-    is(node.nodeName, "row", "Setting should be followed by a row node");
-    is_element_hidden(node, "Descriptions of unsupported settings should not be visible");
-    
     var button = gManagerWindow.document.getElementById("detail-prefs-btn");
     is_element_hidden(button, "Preferences button should not be visible");
 
     gCategoryUtilities.openType("extension", run_next_test);
   });
 });
 
 // Addon with non-inline preferences as optionsURL
--- a/toolkit/themes/gnomestripe/mozapps/extensions/extensions.css
+++ b/toolkit/themes/gnomestripe/mozapps/extensions/extensions.css
@@ -734,41 +734,51 @@ setting[first-row="true"] {
   border-top: none;
 }
 
 .detail-row,
 .detail-row-complex,
 setting {
   border-top: 1px solid ThreeDShadow;
   -moz-box-align: center;
-  min-height: 33px;
+  min-height: 32px;
 }
 
 #detail-controls {
   margin-bottom: 1em;
 }
 
 #detail-view[active="false"]:not([pending]):not([notification]) {
   background-image: -moz-linear-gradient(rgba(135, 135, 135, 0.1),
                                          rgba(135, 135, 135, 0));
 }
 
 setting[first-row="true"] {
   margin-top: 2em;
 }
 
+setting {
+  -moz-box-align: start;
+}
+
+.preferences-alignment {
+  min-height: 32px;
+  -moz-box-align: center;
+}
+
 .preferences-description {
   font-size: 90.9%;
   color: graytext;
   margin-top: -2px;
   -moz-margin-start: 2em;
+  white-space: pre-wrap;
 }
 
-setting[type="string"] > .setting-input > textbox {
-  -moz-box-flex: 1;
+.preferences-description:empty {
+  display: none;
 }
 
 menulist { /* Fixes some styling inconsistencies */
   font-size: 100%;
   margin: 1px 5px 2px 5px;
 }
 
 colorpicker[type="button"] { /* Fixes some styling inconsistencies */
--- a/toolkit/themes/pinstripe/mozapps/extensions/extensions.css
+++ b/toolkit/themes/pinstripe/mozapps/extensions/extensions.css
@@ -929,25 +929,35 @@ setting {
   background-image: -moz-linear-gradient(rgba(135, 135, 135, 0.1),
                                          rgba(135, 135, 135, 0));
 }
 
 setting[first-row="true"] {
   margin-top: 2em;
 }
 
+setting {
+  -moz-box-align: start;
+}
+
+.preferences-alignment {
+  min-height: 30px;
+  -moz-box-align: center;
+}
+
 .preferences-description {
   font-size: 90.9%;
   color: graytext;
   margin-top: -2px;
   -moz-margin-start: 2em;
+  white-space: pre-wrap;
 }
 
-setting[type="string"] > .setting-input > textbox {
-  -moz-box-flex: 1;
+.preferences-description:empty {
+  display: none;
 }
 
 setting[type="radio"] > radiogroup {
   -moz-box-orient: horizontal;
 }
 
 
 /*** creator ***/
--- a/toolkit/themes/winstripe/mozapps/extensions/extensions.css
+++ b/toolkit/themes/winstripe/mozapps/extensions/extensions.css
@@ -908,25 +908,35 @@ setting {
   background-image: -moz-linear-gradient(rgba(135, 135, 135, 0.1),
                                          rgba(135, 135, 135, 0));
 }
 
 setting[first-row="true"] {
   margin-top: 2em;
 }
 
+setting {
+  -moz-box-align: start;
+}
+
+.preferences-alignment {
+  min-height: 30px;
+  -moz-box-align: center;
+}
+
 .preferences-description {
   font-size: 90.9%;
   color: graytext;
   margin-top: -2px;
   -moz-margin-start: 2em;
+  white-space: pre-wrap;
 }
 
-setting[type="string"] > .setting-input > textbox {
-  -moz-box-flex: 1;
+.preferences-description:empty {
+  display: none;
 }
 
 setting[type="radio"] > radiogroup {
   -moz-box-orient: horizontal;
 }
 
 menulist { /* Fixes some styling inconsistencies */
   margin: 1px 5px 2px 5px;