/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "AccIterator.h" #include "AccGroupInfo.h" #ifdef MOZ_XUL #include "XULTreeAccessible.h" #endif #include "mozilla/dom/HTMLLabelElement.h" using namespace mozilla; using namespace mozilla::a11y; //////////////////////////////////////////////////////////////////////////////// // AccIterator //////////////////////////////////////////////////////////////////////////////// AccIterator::AccIterator(Accessible* aAccessible, filters::FilterFuncPtr aFilterFunc) : mFilterFunc(aFilterFunc) { mState = new IteratorState(aAccessible); } AccIterator::~AccIterator() { while (mState) { IteratorState *tmp = mState; mState = tmp->mParentState; delete tmp; } } Accessible* AccIterator::Next() { while (mState) { Accessible* child = mState->mParent->GetChildAt(mState->mIndex++); if (!child) { IteratorState* tmp = mState; mState = mState->mParentState; delete tmp; continue; } uint32_t result = mFilterFunc(child); if (result & filters::eMatch) return child; if (!(result & filters::eSkipSubtree)) { IteratorState* childState = new IteratorState(child, mState); mState = childState; } } return nullptr; } //////////////////////////////////////////////////////////////////////////////// // nsAccIterator::IteratorState AccIterator::IteratorState::IteratorState(Accessible* aParent, IteratorState *mParentState) : mParent(aParent), mIndex(0), mParentState(mParentState) { } //////////////////////////////////////////////////////////////////////////////// // RelatedAccIterator //////////////////////////////////////////////////////////////////////////////// RelatedAccIterator:: RelatedAccIterator(DocAccessible* aDocument, nsIContent* aDependentContent, nsIAtom* aRelAttr) : mDocument(aDocument), mRelAttr(aRelAttr), mProviders(nullptr), mBindingParent(nullptr), mIndex(0) { mBindingParent = aDependentContent->GetBindingParent(); nsIAtom* IDAttr = mBindingParent ? nsGkAtoms::anonid : nsGkAtoms::id; nsAutoString id; if (aDependentContent->GetAttr(kNameSpaceID_None, IDAttr, id)) mProviders = mDocument->mDependentIDsHash.Get(id); } Accessible* RelatedAccIterator::Next() { if (!mProviders) return nullptr; while (mIndex < mProviders->Length()) { DocAccessible::AttrRelProvider* provider = (*mProviders)[mIndex++]; // Return related accessible for the given attribute and if the provider // content is in the same binding in the case of XBL usage. if (provider->mRelAttr == mRelAttr) { nsIContent* bindingParent = provider->mContent->GetBindingParent(); bool inScope = mBindingParent == bindingParent || mBindingParent == provider->mContent; if (inScope) { Accessible* 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; } } } return nullptr; } //////////////////////////////////////////////////////////////////////////////// // HTMLLabelIterator //////////////////////////////////////////////////////////////////////////////// HTMLLabelIterator:: HTMLLabelIterator(DocAccessible* aDocument, const Accessible* aAccessible, LabelFilter aFilter) : mRelIter(aDocument, aAccessible->GetContent(), nsGkAtoms::_for), mAcc(aAccessible), mLabelFilter(aFilter) { } bool HTMLLabelIterator::IsLabel(Accessible* aLabel) { dom::HTMLLabelElement* labelEl = dom::HTMLLabelElement::FromContent(aLabel->GetContent()); return labelEl && labelEl->GetControl() == mAcc->GetContent(); } Accessible* HTMLLabelIterator::Next() { // Get either