accessible/src/base/AccIterator.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 4
michael@0 5 #include "AccIterator.h"
michael@0 6
michael@0 7 #include "AccGroupInfo.h"
michael@0 8 #ifdef MOZ_XUL
michael@0 9 #include "XULTreeAccessible.h"
michael@0 10 #endif
michael@0 11
michael@0 12 #include "mozilla/dom/Element.h"
michael@0 13
michael@0 14 using namespace mozilla;
michael@0 15 using namespace mozilla::a11y;
michael@0 16
michael@0 17 ////////////////////////////////////////////////////////////////////////////////
michael@0 18 // AccIterator
michael@0 19 ////////////////////////////////////////////////////////////////////////////////
michael@0 20
michael@0 21 AccIterator::AccIterator(Accessible* aAccessible,
michael@0 22 filters::FilterFuncPtr aFilterFunc) :
michael@0 23 mFilterFunc(aFilterFunc)
michael@0 24 {
michael@0 25 mState = new IteratorState(aAccessible);
michael@0 26 }
michael@0 27
michael@0 28 AccIterator::~AccIterator()
michael@0 29 {
michael@0 30 while (mState) {
michael@0 31 IteratorState *tmp = mState;
michael@0 32 mState = tmp->mParentState;
michael@0 33 delete tmp;
michael@0 34 }
michael@0 35 }
michael@0 36
michael@0 37 Accessible*
michael@0 38 AccIterator::Next()
michael@0 39 {
michael@0 40 while (mState) {
michael@0 41 Accessible* child = mState->mParent->GetChildAt(mState->mIndex++);
michael@0 42 if (!child) {
michael@0 43 IteratorState* tmp = mState;
michael@0 44 mState = mState->mParentState;
michael@0 45 delete tmp;
michael@0 46
michael@0 47 continue;
michael@0 48 }
michael@0 49
michael@0 50 uint32_t result = mFilterFunc(child);
michael@0 51 if (result & filters::eMatch)
michael@0 52 return child;
michael@0 53
michael@0 54 if (!(result & filters::eSkipSubtree)) {
michael@0 55 IteratorState* childState = new IteratorState(child, mState);
michael@0 56 mState = childState;
michael@0 57 }
michael@0 58 }
michael@0 59
michael@0 60 return nullptr;
michael@0 61 }
michael@0 62
michael@0 63 ////////////////////////////////////////////////////////////////////////////////
michael@0 64 // nsAccIterator::IteratorState
michael@0 65
michael@0 66 AccIterator::IteratorState::IteratorState(Accessible* aParent,
michael@0 67 IteratorState *mParentState) :
michael@0 68 mParent(aParent), mIndex(0), mParentState(mParentState)
michael@0 69 {
michael@0 70 }
michael@0 71
michael@0 72
michael@0 73 ////////////////////////////////////////////////////////////////////////////////
michael@0 74 // RelatedAccIterator
michael@0 75 ////////////////////////////////////////////////////////////////////////////////
michael@0 76
michael@0 77 RelatedAccIterator::
michael@0 78 RelatedAccIterator(DocAccessible* aDocument, nsIContent* aDependentContent,
michael@0 79 nsIAtom* aRelAttr) :
michael@0 80 mDocument(aDocument), mRelAttr(aRelAttr), mProviders(nullptr),
michael@0 81 mBindingParent(nullptr), mIndex(0)
michael@0 82 {
michael@0 83 mBindingParent = aDependentContent->GetBindingParent();
michael@0 84 nsIAtom* IDAttr = mBindingParent ?
michael@0 85 nsGkAtoms::anonid : aDependentContent->GetIDAttributeName();
michael@0 86
michael@0 87 nsAutoString id;
michael@0 88 if (aDependentContent->GetAttr(kNameSpaceID_None, IDAttr, id))
michael@0 89 mProviders = mDocument->mDependentIDsHash.Get(id);
michael@0 90 }
michael@0 91
michael@0 92 Accessible*
michael@0 93 RelatedAccIterator::Next()
michael@0 94 {
michael@0 95 if (!mProviders)
michael@0 96 return nullptr;
michael@0 97
michael@0 98 while (mIndex < mProviders->Length()) {
michael@0 99 DocAccessible::AttrRelProvider* provider = (*mProviders)[mIndex++];
michael@0 100
michael@0 101 // Return related accessible for the given attribute and if the provider
michael@0 102 // content is in the same binding in the case of XBL usage.
michael@0 103 if (provider->mRelAttr == mRelAttr) {
michael@0 104 nsIContent* bindingParent = provider->mContent->GetBindingParent();
michael@0 105 bool inScope = mBindingParent == bindingParent ||
michael@0 106 mBindingParent == provider->mContent;
michael@0 107
michael@0 108 if (inScope) {
michael@0 109 Accessible* related = mDocument->GetAccessible(provider->mContent);
michael@0 110 if (related)
michael@0 111 return related;
michael@0 112
michael@0 113 // If the document content is pointed by relation then return the document
michael@0 114 // itself.
michael@0 115 if (provider->mContent == mDocument->GetContent())
michael@0 116 return mDocument;
michael@0 117 }
michael@0 118 }
michael@0 119 }
michael@0 120
michael@0 121 return nullptr;
michael@0 122 }
michael@0 123
michael@0 124
michael@0 125 ////////////////////////////////////////////////////////////////////////////////
michael@0 126 // HTMLLabelIterator
michael@0 127 ////////////////////////////////////////////////////////////////////////////////
michael@0 128
michael@0 129 HTMLLabelIterator::
michael@0 130 HTMLLabelIterator(DocAccessible* aDocument, const Accessible* aAccessible,
michael@0 131 LabelFilter aFilter) :
michael@0 132 mRelIter(aDocument, aAccessible->GetContent(), nsGkAtoms::_for),
michael@0 133 mAcc(aAccessible), mLabelFilter(aFilter)
michael@0 134 {
michael@0 135 }
michael@0 136
michael@0 137 Accessible*
michael@0 138 HTMLLabelIterator::Next()
michael@0 139 {
michael@0 140 // Get either <label for="[id]"> element which explicitly points to given
michael@0 141 // element, or <label> ancestor which implicitly point to it.
michael@0 142 Accessible* label = nullptr;
michael@0 143 while ((label = mRelIter.Next())) {
michael@0 144 if (label->GetContent()->Tag() == nsGkAtoms::label)
michael@0 145 return label;
michael@0 146 }
michael@0 147
michael@0 148 // Ignore ancestor label on not widget accessible.
michael@0 149 if (mLabelFilter == eSkipAncestorLabel || !mAcc->IsWidget())
michael@0 150 return nullptr;
michael@0 151
michael@0 152 // Go up tree to get a name of ancestor label if there is one (an ancestor
michael@0 153 // <label> implicitly points to us). Don't go up farther than form or
michael@0 154 // document.
michael@0 155 Accessible* walkUp = mAcc->Parent();
michael@0 156 while (walkUp && !walkUp->IsDoc()) {
michael@0 157 nsIContent* walkUpElm = walkUp->GetContent();
michael@0 158 if (walkUpElm->IsHTML()) {
michael@0 159 if (walkUpElm->Tag() == nsGkAtoms::label &&
michael@0 160 !walkUpElm->HasAttr(kNameSpaceID_None, nsGkAtoms::_for)) {
michael@0 161 mLabelFilter = eSkipAncestorLabel; // prevent infinite loop
michael@0 162 return walkUp;
michael@0 163 }
michael@0 164
michael@0 165 if (walkUpElm->Tag() == nsGkAtoms::form)
michael@0 166 break;
michael@0 167 }
michael@0 168
michael@0 169 walkUp = walkUp->Parent();
michael@0 170 }
michael@0 171
michael@0 172 return nullptr;
michael@0 173 }
michael@0 174
michael@0 175
michael@0 176 ////////////////////////////////////////////////////////////////////////////////
michael@0 177 // HTMLOutputIterator
michael@0 178 ////////////////////////////////////////////////////////////////////////////////
michael@0 179
michael@0 180 HTMLOutputIterator::
michael@0 181 HTMLOutputIterator(DocAccessible* aDocument, nsIContent* aElement) :
michael@0 182 mRelIter(aDocument, aElement, nsGkAtoms::_for)
michael@0 183 {
michael@0 184 }
michael@0 185
michael@0 186 Accessible*
michael@0 187 HTMLOutputIterator::Next()
michael@0 188 {
michael@0 189 Accessible* output = nullptr;
michael@0 190 while ((output = mRelIter.Next())) {
michael@0 191 if (output->GetContent()->Tag() == nsGkAtoms::output)
michael@0 192 return output;
michael@0 193 }
michael@0 194
michael@0 195 return nullptr;
michael@0 196 }
michael@0 197
michael@0 198
michael@0 199 ////////////////////////////////////////////////////////////////////////////////
michael@0 200 // XULLabelIterator
michael@0 201 ////////////////////////////////////////////////////////////////////////////////
michael@0 202
michael@0 203 XULLabelIterator::
michael@0 204 XULLabelIterator(DocAccessible* aDocument, nsIContent* aElement) :
michael@0 205 mRelIter(aDocument, aElement, nsGkAtoms::control)
michael@0 206 {
michael@0 207 }
michael@0 208
michael@0 209 Accessible*
michael@0 210 XULLabelIterator::Next()
michael@0 211 {
michael@0 212 Accessible* label = nullptr;
michael@0 213 while ((label = mRelIter.Next())) {
michael@0 214 if (label->GetContent()->Tag() == nsGkAtoms::label)
michael@0 215 return label;
michael@0 216 }
michael@0 217
michael@0 218 return nullptr;
michael@0 219 }
michael@0 220
michael@0 221
michael@0 222 ////////////////////////////////////////////////////////////////////////////////
michael@0 223 // XULDescriptionIterator
michael@0 224 ////////////////////////////////////////////////////////////////////////////////
michael@0 225
michael@0 226 XULDescriptionIterator::
michael@0 227 XULDescriptionIterator(DocAccessible* aDocument, nsIContent* aElement) :
michael@0 228 mRelIter(aDocument, aElement, nsGkAtoms::control)
michael@0 229 {
michael@0 230 }
michael@0 231
michael@0 232 Accessible*
michael@0 233 XULDescriptionIterator::Next()
michael@0 234 {
michael@0 235 Accessible* descr = nullptr;
michael@0 236 while ((descr = mRelIter.Next())) {
michael@0 237 if (descr->GetContent()->Tag() == nsGkAtoms::description)
michael@0 238 return descr;
michael@0 239 }
michael@0 240
michael@0 241 return nullptr;
michael@0 242 }
michael@0 243
michael@0 244 ////////////////////////////////////////////////////////////////////////////////
michael@0 245 // IDRefsIterator
michael@0 246 ////////////////////////////////////////////////////////////////////////////////
michael@0 247
michael@0 248 IDRefsIterator::
michael@0 249 IDRefsIterator(DocAccessible* aDoc, nsIContent* aContent,
michael@0 250 nsIAtom* aIDRefsAttr) :
michael@0 251 mContent(aContent), mDoc(aDoc), mCurrIdx(0)
michael@0 252 {
michael@0 253 if (mContent->IsInDoc())
michael@0 254 mContent->GetAttr(kNameSpaceID_None, aIDRefsAttr, mIDs);
michael@0 255 }
michael@0 256
michael@0 257 const nsDependentSubstring
michael@0 258 IDRefsIterator::NextID()
michael@0 259 {
michael@0 260 for (; mCurrIdx < mIDs.Length(); mCurrIdx++) {
michael@0 261 if (!NS_IsAsciiWhitespace(mIDs[mCurrIdx]))
michael@0 262 break;
michael@0 263 }
michael@0 264
michael@0 265 if (mCurrIdx >= mIDs.Length())
michael@0 266 return nsDependentSubstring();
michael@0 267
michael@0 268 nsAString::index_type idStartIdx = mCurrIdx;
michael@0 269 while (++mCurrIdx < mIDs.Length()) {
michael@0 270 if (NS_IsAsciiWhitespace(mIDs[mCurrIdx]))
michael@0 271 break;
michael@0 272 }
michael@0 273
michael@0 274 return Substring(mIDs, idStartIdx, mCurrIdx++ - idStartIdx);
michael@0 275 }
michael@0 276
michael@0 277 nsIContent*
michael@0 278 IDRefsIterator::NextElem()
michael@0 279 {
michael@0 280 while (true) {
michael@0 281 const nsDependentSubstring id = NextID();
michael@0 282 if (id.IsEmpty())
michael@0 283 break;
michael@0 284
michael@0 285 nsIContent* refContent = GetElem(id);
michael@0 286 if (refContent)
michael@0 287 return refContent;
michael@0 288 }
michael@0 289
michael@0 290 return nullptr;
michael@0 291 }
michael@0 292
michael@0 293 nsIContent*
michael@0 294 IDRefsIterator::GetElem(const nsDependentSubstring& aID)
michael@0 295 {
michael@0 296 // Get elements in DOM tree by ID attribute if this is an explicit content.
michael@0 297 // In case of bound element check its anonymous subtree.
michael@0 298 if (!mContent->IsInAnonymousSubtree()) {
michael@0 299 dom::Element* refElm = mContent->OwnerDoc()->GetElementById(aID);
michael@0 300 if (refElm || !mContent->GetXBLBinding())
michael@0 301 return refElm;
michael@0 302 }
michael@0 303
michael@0 304 // If content is in anonymous subtree or an element having anonymous subtree
michael@0 305 // then use "anonid" attribute to get elements in anonymous subtree.
michael@0 306
michael@0 307 // Check inside the binding the element is contained in.
michael@0 308 nsIContent* bindingParent = mContent->GetBindingParent();
michael@0 309 if (bindingParent) {
michael@0 310 nsIContent* refElm = bindingParent->OwnerDoc()->
michael@0 311 GetAnonymousElementByAttribute(bindingParent, nsGkAtoms::anonid, aID);
michael@0 312
michael@0 313 if (refElm)
michael@0 314 return refElm;
michael@0 315 }
michael@0 316
michael@0 317 // Check inside the binding of the element.
michael@0 318 if (mContent->GetXBLBinding()) {
michael@0 319 return mContent->OwnerDoc()->
michael@0 320 GetAnonymousElementByAttribute(mContent, nsGkAtoms::anonid, aID);
michael@0 321 }
michael@0 322
michael@0 323 return nullptr;
michael@0 324 }
michael@0 325
michael@0 326 Accessible*
michael@0 327 IDRefsIterator::Next()
michael@0 328 {
michael@0 329 nsIContent* nextElm = NextElem();
michael@0 330 return nextElm ? mDoc->GetAccessible(nextElm) : nullptr;
michael@0 331 }
michael@0 332
michael@0 333
michael@0 334 ////////////////////////////////////////////////////////////////////////////////
michael@0 335 // SingleAccIterator
michael@0 336 ////////////////////////////////////////////////////////////////////////////////
michael@0 337
michael@0 338 Accessible*
michael@0 339 SingleAccIterator::Next()
michael@0 340 {
michael@0 341 nsRefPtr<Accessible> nextAcc;
michael@0 342 mAcc.swap(nextAcc);
michael@0 343 return (nextAcc && !nextAcc->IsDefunct()) ? nextAcc : nullptr;
michael@0 344 }
michael@0 345
michael@0 346
michael@0 347 ////////////////////////////////////////////////////////////////////////////////
michael@0 348 // ItemIterator
michael@0 349 ////////////////////////////////////////////////////////////////////////////////
michael@0 350
michael@0 351 Accessible*
michael@0 352 ItemIterator::Next()
michael@0 353 {
michael@0 354 if (mContainer) {
michael@0 355 mAnchor = AccGroupInfo::FirstItemOf(mContainer);
michael@0 356 mContainer = nullptr;
michael@0 357 return mAnchor;
michael@0 358 }
michael@0 359
michael@0 360 return mAnchor ? (mAnchor = AccGroupInfo::NextItemTo(mAnchor)) : nullptr;
michael@0 361 }
michael@0 362
michael@0 363
michael@0 364 ////////////////////////////////////////////////////////////////////////////////
michael@0 365 // XULTreeItemIterator
michael@0 366 ////////////////////////////////////////////////////////////////////////////////
michael@0 367
michael@0 368 XULTreeItemIterator::XULTreeItemIterator(XULTreeAccessible* aXULTree,
michael@0 369 nsITreeView* aTreeView,
michael@0 370 int32_t aRowIdx) :
michael@0 371 mXULTree(aXULTree), mTreeView(aTreeView), mRowCount(-1),
michael@0 372 mContainerLevel(-1), mCurrRowIdx(aRowIdx + 1)
michael@0 373 {
michael@0 374 mTreeView->GetRowCount(&mRowCount);
michael@0 375 if (aRowIdx != -1)
michael@0 376 mTreeView->GetLevel(aRowIdx, &mContainerLevel);
michael@0 377 }
michael@0 378
michael@0 379 Accessible*
michael@0 380 XULTreeItemIterator::Next()
michael@0 381 {
michael@0 382 while (mCurrRowIdx < mRowCount) {
michael@0 383 int32_t level = 0;
michael@0 384 mTreeView->GetLevel(mCurrRowIdx, &level);
michael@0 385
michael@0 386 if (level == mContainerLevel + 1)
michael@0 387 return mXULTree->GetTreeItemAccessible(mCurrRowIdx++);
michael@0 388
michael@0 389 if (level <= mContainerLevel) { // got level up
michael@0 390 mCurrRowIdx = mRowCount;
michael@0 391 break;
michael@0 392 }
michael@0 393
michael@0 394 mCurrRowIdx++;
michael@0 395 }
michael@0 396
michael@0 397 return nullptr;
michael@0 398 }

mercurial