--- a/browser/base/content/test/general/browser_selectpopup.js
+++ b/browser/base/content/test/general/browser_selectpopup.js
@@ -136,16 +136,40 @@ const GENERIC_OPTION_STYLED_AS_IMPORTANT
const TRANSLUCENT_SELECT_BECOMES_OPAQUE =
"<html><head>" +
"<body><select id='one' style='background-color: rgba(255,255,255,.55);'>" +
' <option value="One">{"color": "rgb(0, 0, 0)", "backgroundColor": "rgba(0, 0, 0, 0)"}</option>' +
' <option value="Two" selected="true">{"end": "true"}</option>' +
"</select></body></html>";
+const DISABLED_OPTGROUP_AND_OPTIONS =
+ "<html><head>" +
+ "<body><select id='one'>" +
+ " <optgroup label='{\"color\": \"rgb(0, 0, 0)\", \"backgroundColor\": \"buttonface\"}'>" +
+ ' <option disabled="">{"color": "GrayText", "backgroundColor": "rgba(0, 0, 0, 0)"}</option>' +
+ ' <option>{"color": "rgb(0, 0, 0)", "backgroundColor": "rgba(0, 0, 0, 0)"}</option>' +
+ ' <option disabled="">{"color": "GrayText", "backgroundColor": "rgba(0, 0, 0, 0)"}</option>' +
+ ' <option>{"color": "rgb(0, 0, 0)", "backgroundColor": "rgba(0, 0, 0, 0)"}</option>' +
+ ' <option>{"color": "rgb(0, 0, 0)", "backgroundColor": "rgba(0, 0, 0, 0)"}</option>' +
+ ' <option>{"color": "rgb(0, 0, 0)", "backgroundColor": "rgba(0, 0, 0, 0)"}</option>' +
+ ' <option>{"color": "rgb(0, 0, 0)", "backgroundColor": "rgba(0, 0, 0, 0)"}</option>' +
+ " </optgroup>" +
+ " <optgroup label='{\"color\": \"GrayText\", \"backgroundColor\": \"buttonface\"}' disabled=''>" +
+ ' <option>{"color": "GrayText", "backgroundColor": "rgba(0, 0, 0, 0)"}</option>' +
+ ' <option>{"color": "GrayText", "backgroundColor": "rgba(0, 0, 0, 0)"}</option>' +
+ ' <option>{"color": "GrayText", "backgroundColor": "rgba(0, 0, 0, 0)"}</option>' +
+ ' <option>{"color": "GrayText", "backgroundColor": "rgba(0, 0, 0, 0)"}</option>' +
+ ' <option>{"color": "GrayText", "backgroundColor": "rgba(0, 0, 0, 0)"}</option>' +
+ ' <option>{"color": "GrayText", "backgroundColor": "rgba(0, 0, 0, 0)"}</option>' +
+ ' <option>{"color": "GrayText", "backgroundColor": "rgba(0, 0, 0, 0)"}</option>' +
+ " </optgroup>" +
+ ' <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 {
@@ -200,17 +224,25 @@ function getSystemColor(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);
+ let expected;
+ try {
+ expected = JSON.parse(item.label);
+ } catch (ex) {
+ info(`Failed parsing: ${item.label}`);
+ info(`Failed parsing element with outerHTML: ${item.outerHTML}`);
+ ok(false, ex.message);
+ return;
+ }
for (let color of Object.keys(expected)) {
if (color.toLowerCase().includes("color") &&
!expected[color].startsWith("rgb")) {
expected[color] = getSystemColor(expected[color]);
}
}
@@ -948,8 +980,18 @@ add_task(function* test_translucent_sele
// The popup is requested to show a translucent background
// but we force the alpha channel to 1 on the popup.
let options = {
selectColor: "rgb(0, 0, 0)",
selectBgColor: "rgb(255, 255, 255)"
};
yield testSelectColors(TRANSLUCENT_SELECT_BECOMES_OPAQUE, 2, options);
});
+
+add_task(function* test_disabled_optgroup_and_options() {
+ // The colors used by this test are platform-specific.
+ if (AppConstants.platform != "win") {
+ return;
+ }
+
+ yield testSelectColors(DISABLED_OPTGROUP_AND_OPTIONS, 17,
+ {skipSelectColorTest: true});
+});
--- a/toolkit/modules/SelectParentHelper.jsm
+++ b/toolkit/modules/SelectParentHelper.jsm
@@ -270,20 +270,19 @@ function populateChildren(menulist, opti
if (customStylingEnabled &&
option.color &&
option.color != uaColor) {
ruleBody += `color: ${option.color};`;
}
if (ruleBody) {
- sheet.insertRule(`${item.localName}:nth-child(${nthChildIndex}):not([_moz-menuactive="true"]) {
+ sheet.insertRule(`menupopup > :nth-child(${nthChildIndex}):not([_moz-menuactive="true"]) {
${ruleBody}
}`, 0);
-
item.setAttribute("customoptionstyling", "true");
} else {
item.removeAttribute("customoptionstyling");
}
element.appendChild(item);
nthChildIndex++;
@@ -292,17 +291,17 @@ function populateChildren(menulist, opti
if (isDisabled) {
item.setAttribute("disabled", "true");
}
if (isOptGroup) {
nthChildIndex =
populateChildren(menulist, option.children, selectedIndex, zoom,
uaBackgroundColor, uaColor, sheet,
- item, isDisabled, adjustedTextSize, false);
+ item, isDisabled, adjustedTextSize, false, nthChildIndex);
} else {
if (option.index == selectedIndex) {
// We expect the parent element of the popup to be a <xul:menulist> that
// has the popuponly attribute set to "true". This is necessary in order
// for a <xul:menupopup> to act like a proper <html:select> dropdown, as
// the <xul:menulist> does things like remember state and set the
// _moz-menuactive attribute on the selected <xul:menuitem>.
menulist.selectedItem = item;