summaryrefslogtreecommitdiffstats
path: root/accessible/base/AccIterator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'accessible/base/AccIterator.cpp')
-rw-r--r--accessible/base/AccIterator.cpp60
1 files changed, 48 insertions, 12 deletions
diff --git a/accessible/base/AccIterator.cpp b/accessible/base/AccIterator.cpp
index badd34c0d5..d28d5fcbe9 100644
--- a/accessible/base/AccIterator.cpp
+++ b/accessible/base/AccIterator.cpp
@@ -71,7 +71,12 @@ AccIterator::IteratorState::IteratorState(const LocalAccessible* aParent,
RelatedAccIterator::RelatedAccIterator(DocAccessible* aDocument,
nsIContent* aDependentContent,
nsAtom* aRelAttr)
- : mDocument(aDocument), mRelAttr(aRelAttr), mProviders(nullptr), mIndex(0) {
+ : mDocument(aDocument),
+ mDependentContent(aDependentContent),
+ mRelAttr(aRelAttr),
+ mProviders(nullptr),
+ mIndex(0),
+ mIsWalkingDependentElements(false) {
nsAutoString id;
if (aDependentContent->IsElement() &&
aDependentContent->AsElement()->GetAttr(nsGkAtoms::id, id)) {
@@ -80,26 +85,57 @@ RelatedAccIterator::RelatedAccIterator(DocAccessible* aDocument,
}
LocalAccessible* RelatedAccIterator::Next() {
- if (!mProviders) return nullptr;
+ if (!mProviders || mIndex == mProviders->Length()) {
+ if (mIsWalkingDependentElements) {
+ // We've walked both dependent ids and dependent elements, so there are
+ // no more targets.
+ return nullptr;
+ }
+ // We've returned all dependent ids, but there might be dependent elements
+ // too. Walk those next.
+ mIsWalkingDependentElements = true;
+ mIndex = 0;
+ if (auto providers =
+ mDocument->mDependentElementsMap.Lookup(mDependentContent)) {
+ mProviders = &providers.Data();
+ } else {
+ mProviders = nullptr;
+ return nullptr;
+ }
+ }
while (mIndex < mProviders->Length()) {
const auto& provider = (*mProviders)[mIndex++];
// Return related accessible for the given attribute.
- if (provider->mRelAttr == mRelAttr) {
- LocalAccessible* related = mDocument->GetAccessible(provider->mContent);
- if (related) {
- return related;
- }
+ if (mRelAttr && provider->mRelAttr != mRelAttr) {
+ continue;
+ }
+ // If we're walking elements (not ids), the explicitly set attr-element
+ // `mDependentContent` must be a descendant of any of the refering element
+ // `mProvider->mContent`'s shadow-including ancestors.
+ if (mIsWalkingDependentElements &&
+ !nsCoreUtils::IsDescendantOfAnyShadowIncludingAncestor(
+ mDependentContent, provider->mContent)) {
+ continue;
+ }
+ LocalAccessible* related = mDocument->GetAccessible(provider->mContent);
+ if (related) {
+ return related;
+ }
- // If the document content is pointed by relation then return the
- // document itself.
- if (provider->mContent == mDocument->GetContent()) {
- return mDocument;
- }
+ // If the document content is pointed by relation then return the
+ // document itself.
+ if (provider->mContent == mDocument->GetContent()) {
+ return mDocument;
}
}
+ // We exhausted mProviders without returning anything.
+ if (!mIsWalkingDependentElements) {
+ // Call this function again to start walking the dependent elements.
+ return Next();
+ }
return nullptr;
}