diff --git a/accessible/android/AccessibleWrap.cpp b/accessible/android/AccessibleWrap.cpp index a89076ff7fc2..db6f89f2e4f1 100644 --- a/accessible/android/AccessibleWrap.cpp +++ b/accessible/android/AccessibleWrap.cpp @@ -419,9 +419,12 @@ mozilla::java::GeckoBundle::LocalRef AccessibleWrap::ToBundle(bool aSmall) { Value(textValue); nsAutoString nodeID; WrapperDOMNodeID(nodeID); + nsAutoString description; + Description(description); if (aSmall) { - return ToBundle(State(), Bounds(), ActionCount(), name, textValue, nodeID); + return ToBundle(State(), Bounds(), ActionCount(), name, textValue, nodeID, + description); } double curValue = UnspecifiedNaN(); @@ -433,15 +436,15 @@ mozilla::java::GeckoBundle::LocalRef AccessibleWrap::ToBundle(bool aSmall) { nsCOMPtr attributes = Attributes(); return ToBundle(State(), Bounds(), ActionCount(), name, textValue, nodeID, - curValue, minValue, maxValue, step, attributes); + description, curValue, minValue, maxValue, step, attributes); } mozilla::java::GeckoBundle::LocalRef AccessibleWrap::ToBundle( const uint64_t aState, const nsIntRect& aBounds, const uint8_t aActionCount, const nsString& aName, const nsString& aTextValue, - const nsString& aDOMNodeID, const double& aCurVal, const double& aMinVal, - const double& aMaxVal, const double& aStep, - nsIPersistentProperties* aAttributes) { + const nsString& aDOMNodeID, const nsString& aDescription, + const double& aCurVal, const double& aMinVal, const double& aMaxVal, + const double& aStep, nsIPersistentProperties* aAttributes) { if (!IsProxy() && IsDefunct()) { return nullptr; } @@ -461,10 +464,18 @@ mozilla::java::GeckoBundle::LocalRef AccessibleWrap::ToBundle( java::sdk::Integer::ValueOf(AndroidClass())); if (aState & states::EDITABLE) { - GECKOBUNDLE_PUT(nodeInfo, "hint", jni::StringParam(aName)); + nsAutoString hint(aName); + if (!aDescription.IsEmpty()) { + hint.AppendLiteral(" "); + hint.Append(aDescription); + } + GECKOBUNDLE_PUT(nodeInfo, "hint", jni::StringParam(hint)); GECKOBUNDLE_PUT(nodeInfo, "text", jni::StringParam(aTextValue)); } else { GECKOBUNDLE_PUT(nodeInfo, "text", jni::StringParam(aName)); + if (!aDescription.IsEmpty()) { + GECKOBUNDLE_PUT(nodeInfo, "hint", jni::StringParam(aDescription)); + } } nsAutoString geckoRole; diff --git a/accessible/android/AccessibleWrap.h b/accessible/android/AccessibleWrap.h index 7e74598ed80c..4899c79c4960 100644 --- a/accessible/android/AccessibleWrap.h +++ b/accessible/android/AccessibleWrap.h @@ -39,6 +39,7 @@ class AccessibleWrap : public Accessible { const uint64_t aState, const nsIntRect& aBounds, const uint8_t aActionCount, const nsString& aName, const nsString& aTextValue, const nsString& aDOMNodeID, + const nsString& aDescription, const double& aCurVal = UnspecifiedNaN(), const double& aMinVal = UnspecifiedNaN(), const double& aMaxVal = UnspecifiedNaN(), diff --git a/accessible/android/DocAccessibleWrap.cpp b/accessible/android/DocAccessibleWrap.cpp index f5edac504949..8b1b931fcd73 100644 --- a/accessible/android/DocAccessibleWrap.cpp +++ b/accessible/android/DocAccessibleWrap.cpp @@ -140,11 +140,13 @@ void DocAccessibleWrap::CacheViewportCallback(nsITimer* aTimer, accessible->Value(textValue); nsAutoString nodeID; static_cast(accessible)->WrapperDOMNodeID(nodeID); + nsAutoString description; + accessible->Description(description); cacheData.AppendElement( BatchData(accessible->Document()->IPCDoc(), uid, accessible->State(), accessible->Bounds(), accessible->ActionCount(), name, - textValue, nodeID, UnspecifiedNaN(), + textValue, nodeID, description, UnspecifiedNaN(), UnspecifiedNaN(), UnspecifiedNaN(), UnspecifiedNaN(), nsTArray())); } @@ -205,13 +207,16 @@ void DocAccessibleWrap::CacheFocusPath(AccessibleWrap* aAccessible) { acc->Value(textValue); nsAutoString nodeID; acc->WrapperDOMNodeID(nodeID); + nsAutoString description; + acc->Description(description); nsCOMPtr props = acc->Attributes(); nsTArray attributes; nsAccUtils::PersistentPropertiesToArray(props, &attributes); - cacheData.AppendElement(BatchData( - acc->Document()->IPCDoc(), uid, acc->State(), acc->Bounds(), - acc->ActionCount(), name, textValue, nodeID, acc->CurValue(), - acc->MinValue(), acc->MaxValue(), acc->Step(), attributes)); + cacheData.AppendElement( + BatchData(acc->Document()->IPCDoc(), uid, acc->State(), acc->Bounds(), + acc->ActionCount(), name, textValue, nodeID, description, + acc->CurValue(), acc->MinValue(), acc->MaxValue(), + acc->Step(), attributes)); mFocusPath.Put(acc->UniqueID(), acc); } @@ -247,11 +252,12 @@ void DocAccessibleWrap::UpdateFocusPathBounds() { auto uid = accessible->IsDoc() && accessible->AsDoc()->IPCDoc() ? 0 : reinterpret_cast(accessible->UniqueID()); - boundsData.AppendElement(BatchData( - accessible->Document()->IPCDoc(), uid, 0, accessible->Bounds(), 0, - nsString(), nsString(), nsString(), UnspecifiedNaN(), - UnspecifiedNaN(), UnspecifiedNaN(), - UnspecifiedNaN(), nsTArray())); + boundsData.AppendElement( + BatchData(accessible->Document()->IPCDoc(), uid, 0, + accessible->Bounds(), 0, nsString(), nsString(), nsString(), + nsString(), UnspecifiedNaN(), + UnspecifiedNaN(), UnspecifiedNaN(), + UnspecifiedNaN(), nsTArray())); } ipcDoc->SendBatch(eBatch_BoundsUpdate, boundsData); diff --git a/accessible/android/SessionAccessibility.cpp b/accessible/android/SessionAccessibility.cpp index 178e8506cb32..37564f0debfb 100644 --- a/accessible/android/SessionAccessibility.cpp +++ b/accessible/android/SessionAccessibility.cpp @@ -332,9 +332,9 @@ void SessionAccessibility::ReplaceViewportCache( AccessibleWrap* acc = aAccessibles.ElementAt(i); if (aData.Length() == aAccessibles.Length()) { const BatchData& data = aData.ElementAt(i); - auto bundle = - acc->ToBundle(data.State(), data.Bounds(), data.ActionCount(), - data.Name(), data.TextValue(), data.DOMNodeID()); + auto bundle = acc->ToBundle( + data.State(), data.Bounds(), data.ActionCount(), data.Name(), + data.TextValue(), data.DOMNodeID(), data.Description()); infos->SetElement(i, bundle); } else { infos->SetElement(i, acc->ToBundle(true)); @@ -354,10 +354,11 @@ void SessionAccessibility::ReplaceFocusPathCache( const BatchData& data = aData.ElementAt(i); nsCOMPtr props = AccessibleWrap::AttributeArrayToProperties(data.Attributes()); - auto bundle = acc->ToBundle( - data.State(), data.Bounds(), data.ActionCount(), data.Name(), - data.TextValue(), data.DOMNodeID(), data.CurValue(), data.MinValue(), - data.MaxValue(), data.Step(), props); + auto bundle = + acc->ToBundle(data.State(), data.Bounds(), data.ActionCount(), + data.Name(), data.TextValue(), data.DOMNodeID(), + data.Description(), data.CurValue(), data.MinValue(), + data.MaxValue(), data.Step(), props); infos->SetElement(i, bundle); } else { infos->SetElement(i, acc->ToBundle()); @@ -380,9 +381,9 @@ void SessionAccessibility::UpdateCachedBounds( if (aData.Length() == aAccessibles.Length()) { const BatchData& data = aData.ElementAt(i); - auto bundle = - acc->ToBundle(data.State(), data.Bounds(), data.ActionCount(), - data.Name(), data.TextValue(), data.DOMNodeID()); + auto bundle = acc->ToBundle( + data.State(), data.Bounds(), data.ActionCount(), data.Name(), + data.TextValue(), data.DOMNodeID(), data.Description()); infos->SetElement(i, bundle); } else { infos->SetElement(i, acc->ToBundle(true)); diff --git a/accessible/ipc/other/PDocAccessible.ipdl b/accessible/ipc/other/PDocAccessible.ipdl index 2c61f51b6a2c..b1123d209943 100644 --- a/accessible/ipc/other/PDocAccessible.ipdl +++ b/accessible/ipc/other/PDocAccessible.ipdl @@ -40,6 +40,7 @@ struct BatchData nsString Name; nsString TextValue; nsString DOMNodeID; + nsString Description; double CurValue; double MinValue; double MaxValue; diff --git a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/AccessibilityTest.kt b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/AccessibilityTest.kt index 3c51b705ac14..2cb7357c56cc 100644 --- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/AccessibilityTest.kt +++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/AccessibilityTest.kt @@ -229,7 +229,7 @@ class AccessibilityTest : BaseSessionTest() { } @Test fun testTextEntryNode() { - sessionRule.session.loadString("", "text/html") + sessionRule.session.loadString("
description
", "text/html") waitForInitialFocus() mainSession.evaluateJS("$('input').focus()") @@ -244,7 +244,7 @@ class AccessibilityTest : BaseSessionTest() { if (Build.VERSION.SDK_INT >= 19) { assertThat("Hint has field name", node.extras.getString("AccessibilityNodeInfo.hint"), - equalTo("Name")) + equalTo("Name description")) } } }) @@ -514,7 +514,7 @@ class AccessibilityTest : BaseSessionTest() { @Test fun testCheckbox() { var nodeId = AccessibilityNodeProvider.HOST_VIEW_ID; - sessionRule.session.loadString("", "text/html") + sessionRule.session.loadString("
description
", "text/html") waitForInitialFocus(true) sessionRule.waitUntilCalled(object : EventDelegate { @@ -527,6 +527,11 @@ class AccessibilityTest : BaseSessionTest() { assertThat("Checkbox node is focusable", node.isFocusable, equalTo(true)) assertThat("Checkbox node is not checked", node.isChecked, equalTo(false)) assertThat("Checkbox node has correct role", node.text.toString(), equalTo("many option")) + if (Build.VERSION.SDK_INT >= 19) { + assertThat("Hint has description", node.extras.getString("AccessibilityNodeInfo.hint"), + equalTo("description")) + } + } })