Accessible* TreeWalker::AccessibleFor(nsIContent* aNode, uint32_t aFlags, bool* aSkipSubtree) { // Ignore the accessible and its subtree if it was repositioned by means // of aria-owns. Accessible* child = mDoc->GetAccessible(aNode); if (child) { if (child->IsRelocated()) { *aSkipSubtree = true; return nullptr; } return child; } // Create an accessible if allowed. if (!(aFlags & eWalkCache) && mContext->IsAcceptableChild(aNode)) { // We may have ARIA owned element in the dependent attributes map, but the // element may be not allowed for this ARIA owns relation, if the relation // crosses out XBL anonymous content boundaries. In this case we won't // create an accessible object for it, when aria-owns is processed, which // may make the element subtree inaccessible. To avoid that let's create // an accessible object now, and later, if allowed, move it in the tree, // when aria-owns relation is processed. if (mDoc->RelocateARIAOwnedIfNeeded(aNode) && !aNode->IsXULElement()) { *aSkipSubtree = true; return nullptr; } return GetAccService()->CreateAccessible(aNode, mContext, aSkipSubtree); } return nullptr; }
bool TreeWalker::Seek(nsIContent* aChildNode) { MOZ_ASSERT(aChildNode, "Child cannot be null"); Reset(); if (mAnchorNode == aChildNode) { return true; } nsIContent* childNode = nullptr; nsINode* parentNode = aChildNode; do { childNode = parentNode->AsContent(); parentNode = childNode->HasFlag(NODE_MAY_BE_IN_BINDING_MNGR) && (mChildFilter & nsIContent::eAllButXBL) ? childNode->GetParentNode() : childNode->GetFlattenedTreeParent(); if (!parentNode || !parentNode->IsElement()) { return false; } // If ARIA owned child. Accessible* child = mDoc->GetAccessible(childNode); if (child && child->IsRelocated()) { MOZ_ASSERT(!(mFlags & eScoped), "Walker should not be scoped when seeking into relocated children"); if (child->Parent() != mContext) { return false; } Accessible* ownedChild = nullptr; while ((ownedChild = mDoc->ARIAOwnedAt(mContext, mARIAOwnsIdx++)) && ownedChild != child); MOZ_ASSERT(ownedChild, "A child has to be in ARIA owned elements"); mPhase = eAtARIAOwns; return true; } // Look in DOM. dom::AllChildrenIterator* iter = PrependState(parentNode->AsElement(), true); if (!iter->Seek(childNode)) { return false; } if (parentNode == mAnchorNode) { mPhase = eAtDOM; return true; } } while (true); return false; }
Accessible* TreeWalker::AccessibleFor(nsIContent* aNode, uint32_t aFlags, bool* aSkipSubtree) { Accessible* child = nullptr; if (aFlags & eWalkCache) { child = mDoc->GetAccessible(aNode); } else if (mContext->IsAcceptableChild(aNode)) { child = GetAccService()-> GetOrCreateAccessible(aNode, mContext, aSkipSubtree); } // Ignore the accessible and its subtree if it was repositioned by means // of aria-owns. if (child && child->IsRelocated()) { *aSkipSubtree = true; return nullptr; } return child; }
nsIContent* TreeWalker::Next(ChildrenIterator* aIter, Accessible** aAccesible, bool* aSkipSubtree) { nsIContent* childEl = aIter->mDOMIter.GetNextChild(); if (!aAccesible) return childEl; *aAccesible = nullptr; *aSkipSubtree = false; if (childEl) { Accessible* accessible = mFlags & eWalkCache ? mDoc->GetAccessible(childEl) : GetAccService()->GetOrCreateAccessible(childEl, mContext, aSkipSubtree); // Ignore the accessible and its subtree if it was repositioned by means of // aria-owns. if (accessible) { if (accessible->IsRelocated()) { *aSkipSubtree = true; } else { *aAccesible = accessible; } } return childEl; } // At last iterate over ARIA owned children. Accessible* parent = mDoc->GetAccessible(aIter->mDOMIter.Parent()); if (parent) { Accessible* child = mDoc->ARIAOwnedAt(parent, aIter->mARIAOwnsIdx++); if (child) { *aAccesible = child; return child->GetContent(); } } return nullptr; }