diff --git a/accessible/generic/LocalAccessible.cpp b/accessible/generic/LocalAccessible.cpp index 99ac02fa6668..b9d67fe33c5e 100644 --- a/accessible/generic/LocalAccessible.cpp +++ b/accessible/generic/LocalAccessible.cpp @@ -1641,7 +1641,9 @@ void LocalAccessible::Value(nsString& aValue) const { } } - if (option) nsTextEquivUtils::GetTextEquivFromSubtree(option, aValue); + // If there's a selected item, get the value from it. Otherwise, determine + // the value from descendant elements. + nsTextEquivUtils::GetTextEquivFromSubtree(option ? option : this, aValue); } } diff --git a/accessible/ipc/RemoteAccessibleBase.cpp b/accessible/ipc/RemoteAccessibleBase.cpp index 6951ad8b592f..9b85fb2f5672 100644 --- a/accessible/ipc/RemoteAccessibleBase.cpp +++ b/accessible/ipc/RemoteAccessibleBase.cpp @@ -267,6 +267,9 @@ void RemoteAccessibleBase::Value(nsString& aValue) const { const_cast*>(this)->GetSelectedItem(0); if (option) { option->Name(aValue); + } else { + // If no selected item, determine the value from descendant elements. + nsTextEquivUtils::GetTextEquivFromSubtree(this, aValue); } return; } diff --git a/accessible/tests/browser/e10s/browser_caching_value.js b/accessible/tests/browser/e10s/browser_caching_value.js index 15b79fb968e0..dd235677292d 100644 --- a/accessible/tests/browser/e10s/browser_caching_value.js +++ b/accessible/tests/browser/e10s/browser_caching_value.js @@ -316,5 +316,69 @@ addAccessibleTask( "Select value correct after changing option back" ); }, - { chrome: true, topLevel: true, iframe: true, remoteIFrame: true } + { chrome: true, topLevel: true, iframe: true, remoteIframe: true } +); + +/** + * Test combobox values for non-editable comboboxes. + */ +addAccessibleTask( + ` +
value
+
+
+
value
+
+
+
+
value
+
+
foo +
+
bar
+
+
+ + + testing + +
+
+
value
+
+
+`, + async function(browser, docAcc) { + const comboDiv1 = findAccessibleChildByID(docAcc, "combo-div-1"); + const comboDiv2 = findAccessibleChildByID(docAcc, "combo-div-2"); + const comboDiv3 = findAccessibleChildByID(docAcc, "combo-div-3"); + const comboDiv4 = findAccessibleChildByID(docAcc, "combo-div-4"); + const comboInput1 = findAccessibleChildByID(docAcc, "combo-input-1"); + const comboInput2 = findAccessibleChildByID(docAcc, "combo-input-2"); + const comboDivSelected = findAccessibleChildByID( + docAcc, + "combo-div-selected" + ); + + // Text as a descendant of the combobox: included in the value. + is(comboDiv1.value, "value", "Combobox value correct"); + + // Text as the descendant of a listbox: excluded from the value. + is(comboDiv2.value, "", "Combobox value correct"); + + // Text as the descendant of some other role that includes text in name computation. + // Here, the group role contains the text node with "value" in it. + is(comboDiv3.value, "value", "Combobox value correct"); + + // Some descendant text included, but text descendant of a listbox excluded. + is(comboDiv4.value, "foo", "Combobox value correct"); + + // Combobox inputs with explicit value report that value. + is(comboInput1.value, "value", "Combobox value correct"); + is(comboInput2.value, "value", "Combobox value correct"); + + // Combobox role with aria-selected reports correct value. + is(comboDivSelected.value, "value", "Combobox value correct"); + }, + { chrome: true, iframe: true, remoteIframe: true } );