Bug 1338850 - Only set the background color and foreground color on the select element if it is not transparent or equal to each other. r=mconley
authorJared Wein <jwein@mozilla.com>
Wed, 15 Feb 2017 13:30:50 -0500
changeset 389929 233d2f9b0cce98d3df6041d187b30a96d1381c26
parent 389928 05efc3638dd900fb7074c7d7f0deacbb9c76a77d
child 389930 35ddc6aaed8b049f3c8dc4b05a701bf92409fb92
push id7198
push userjlorenzo@mozilla.com
push dateTue, 18 Apr 2017 12:07:49 +0000
treeherdermozilla-beta@d57aa49c3948 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmconley
bugs1338850
milestone54.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 1338850 - Only set the background color and foreground color on the select element if it is not transparent or equal to each other. r=mconley MozReview-Commit-ID: AjzZhoBbcFL
browser/base/content/test/general/browser_selectpopup.js
toolkit/modules/SelectParentHelper.jsm
--- a/browser/base/content/test/general/browser_selectpopup.js
+++ b/browser/base/content/test/general/browser_selectpopup.js
@@ -102,16 +102,25 @@ const PAGECONTENT_COLORS_ON_SELECT =
   "</style>" +
   "<body><select id='one'>" +
   '  <option value="One">{"color": "rgb(255, 255, 255)", "backgroundColor": "transparent"}</option>' +
   '  <option value="Two">{"color": "rgb(255, 255, 255)", "backgroundColor": "transparent"}</option>' +
   '  <option value="Three">{"color": "rgb(255, 255, 255)", "backgroundColor": "transparent"}</option>' +
   '  <option value="Four" selected="true">{"end": "true"}</option>' +
   "</select></body></html>";
 
+const TRANSPARENT_SELECT =
+  "<html><head><style>" +
+  "  #one { background-color: transparent; }" +
+  "</style>" +
+  "<body><select id='one'>" +
+  '  <option value="One">{"unstyled": "true"}</option>' +
+  '  <option value="Two" selected="true">{"end": "true"}</option>' +
+  "</select></body></html>";
+
 function openSelectPopup(selectPopup, mode = "key", selector = "select", win = window) {
   let popupShownPromise = BrowserTestUtils.waitForEvent(selectPopup, "popupshown");
 
   if (mode == "click" || mode == "mousedown") {
     let mousePromise;
     if (mode == "click") {
       mousePromise = BrowserTestUtils.synthesizeMouseAtCenter(selector, { }, win.gBrowser.selectedBrowser);
     } else {
@@ -156,26 +165,32 @@ function getChangeEvents() {
 }
 
 function getClickEvents() {
   return ContentTask.spawn(gBrowser.selectedBrowser, {}, function() {
     return content.wrappedJSObject.gClickEvents;
   });
 }
 
+function getSystemColor(color) {
+  // Need to convert system color to RGB color.
+  let textarea = document.createElementNS("http://www.w3.org/1999/xhtml", "textarea");
+  textarea.style.color = color;
+  return getComputedStyle(textarea).color;
+}
+
 function testOptionColors(index, item, menulist) {
+  // The label contains a JSON string of the expected colors for
+  // `color` and `background-color`.
   let expected = JSON.parse(item.label);
 
   for (let color of Object.keys(expected)) {
     if (color.toLowerCase().includes("color") &&
         !expected[color].startsWith("rgb")) {
-      // Need to convert system color to RGB color.
-      let textarea = document.createElementNS("http://www.w3.org/1999/xhtml", "textarea");
-      textarea.style.color = expected[color];
-      expected[color] = getComputedStyle(textarea).color;
+      expected[color] = getSystemColor(expected[color]);
     }
   }
 
   // Press Down to move the selected item to the next item in the
   // list and check the colors of this item when it's not selected.
   EventUtils.synthesizeKey("KEY_ArrowDown", { code: "ArrowDown" });
 
   if (expected.end) {
@@ -824,18 +839,16 @@ add_task(function* test_colors_applied_t
 
   let menulist = document.getElementById("ContentSelectDropdown");
   let selectPopup = menulist.menupopup;
 
   let popupShownPromise = BrowserTestUtils.waitForEvent(selectPopup, "popupshown");
   yield BrowserTestUtils.synthesizeMouseAtCenter("#one", { type: "mousedown" }, gBrowser.selectedBrowser);
   yield popupShownPromise;
 
-  // The label contains a JSON string of the expected colors for
-  // `color` and `background-color`.
   is(selectPopup.parentNode.itemCount, 4, "Correct number of items");
   let child = selectPopup.firstChild;
   let idx = 1;
 
   is(getComputedStyle(selectPopup).color, "rgb(255, 255, 255)",
     "popup has expected foreground color");
   is(getComputedStyle(selectPopup).backgroundColor, "rgb(126, 58, 58)",
     "popup has expected background color");
@@ -843,16 +856,50 @@ add_task(function* test_colors_applied_t
   ok(!child.selected, "The first child should not be selected");
   while (child) {
     testOptionColors(idx, child, menulist);
     idx++;
     child = child.nextSibling;
   }
 
   yield hideSelectPopup(selectPopup, "escape");
+
+  yield BrowserTestUtils.removeTab(tab);
+});
+
+// This test checks when a <select> element has a transparent background applied to itself.
+add_task(function* test_transparent_applied_to_popup() {
+  const pageUrl = "data:text/html," + escape(TRANSPARENT_SELECT);
+  let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, pageUrl);
+
+  let menulist = document.getElementById("ContentSelectDropdown");
+  let selectPopup = menulist.menupopup;
+
+  let popupShownPromise = BrowserTestUtils.waitForEvent(selectPopup, "popupshown");
+  yield BrowserTestUtils.synthesizeMouseAtCenter("#one", { type: "mousedown" }, gBrowser.selectedBrowser);
+  yield popupShownPromise;
+
+  is(selectPopup.parentNode.itemCount, 2, "Correct number of items");
+  let child = selectPopup.firstChild;
+  let idx = 1;
+
+  is(getComputedStyle(selectPopup).color, getSystemColor("-moz-ComboboxText"),
+    "popup has expected foreground color");
+  is(getComputedStyle(selectPopup).backgroundColor, getSystemColor("-moz-Combobox"),
+    "popup has expected background color");
+
+  ok(!child.selected, "The first child should not be selected");
+  while (child) {
+    testOptionColors(idx, child, menulist);
+    idx++;
+    child = child.nextSibling;
+  }
+
+  yield hideSelectPopup(selectPopup, "escape");
+
   yield BrowserTestUtils.removeTab(tab);
 });
 
 // This test checks that the popup is closed when the select element is blurred.
 add_task(function* test_blur_hides_popup() {
   const pageUrl = "data:text/html," + escape(PAGECONTENT_SMALL);
   let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, pageUrl);
 
--- a/toolkit/modules/SelectParentHelper.jsm
+++ b/toolkit/modules/SelectParentHelper.jsm
@@ -37,21 +37,36 @@ this.SelectParentHelper = {
     let doc = menulist.ownerDocument;
     stylesheet = doc.createElementNS("http://www.w3.org/1999/xhtml", "style");
     stylesheet.setAttribute("id", "ContentSelectDropdownScopedStylesheet");
     stylesheet.scoped = true;
     stylesheet.hidden = true;
     stylesheet = menulist.appendChild(stylesheet);
 
     let sheet = stylesheet.sheet;
-    if (selectBackgroundColor != uaSelectBackgroundColor ||
-        selectColor != uaSelectColor) {
+    let ruleBody = "";
+
+    // Some webpages set the <select> backgroundColor to transparent,
+    // but they don't intend to change the popup to transparent.
+    if (selectBackgroundColor != uaSelectBackgroundColor &&
+        selectBackgroundColor != "transparent" &&
+        selectBackgroundColor != selectColor) {
+      ruleBody = `background-color: ${selectBackgroundColor};`;
+    }
+
+    if (selectColor != uaSelectColor &&
+        selectColor != selectBackgroundColor &&
+        (selectBackgroundColor != "transparent" ||
+         selectColor != uaSelectBackgroundColor)) {
+      ruleBody += `color: ${selectColor};`;
+    }
+
+    if (ruleBody) {
       sheet.insertRule(`menupopup {
-        background-color: ${selectBackgroundColor};
-        color: ${selectColor};
+        ${ruleBody}
       }`, 0);
       menulist.menupopup.setAttribute("customoptionstyling", "true");
     } else {
       menulist.menupopup.removeAttribute("customoptionstyling");
     }
 
     currentZoom = zoom;
     currentMenulist = menulist;