From 99e3c36599235925d3d303593ac81768dfcb3ddd Mon Sep 17 00:00:00 2001 From: Alexander Surkov Date: Tue, 16 Nov 2010 22:32:15 -0500 Subject: [PATCH] Bug 573469 - part1, add iterator for IDRefs elements, r=fherrera, sr=neil, a=blockingFinal+ --- accessible/src/base/nsCoreUtils.cpp | 133 ++++++++++-------- accessible/src/base/nsCoreUtils.h | 41 ++++-- accessible/src/base/nsRelUtils.cpp | 23 +-- accessible/src/base/nsTextEquivUtils.cpp | 22 +-- accessible/src/html/nsHTMLTableAccessible.cpp | 35 ++--- 5 files changed, 126 insertions(+), 128 deletions(-) diff --git a/accessible/src/base/nsCoreUtils.cpp b/accessible/src/base/nsCoreUtils.cpp index dfe601b56ba3..380c97ce93d4 100644 --- a/accessible/src/base/nsCoreUtils.cpp +++ b/accessible/src/base/nsCoreUtils.cpp @@ -47,7 +47,6 @@ #include "nsIDOM3Node.h" #include "nsIDOMDocument.h" #include "nsIDOMDocumentView.h" -#include "nsIDOMDocumentXBL.h" #include "nsIDOMHTMLDocument.h" #include "nsIDOMHTMLElement.h" #include "nsIDOMNodeList.h" @@ -805,67 +804,6 @@ nsCoreUtils::GetLanguageFor(nsIContent *aContent, nsIContent *aRootContent, walkUp = walkUp->GetParent(); } -void -nsCoreUtils::GetElementsByIDRefsAttr(nsIContent *aContent, nsIAtom *aAttr, - nsIArray **aRefElements) -{ - *aRefElements = nsnull; - - nsAutoString ids; - if (!aContent->GetAttr(kNameSpaceID_None, aAttr, ids)) - return; - - ids.CompressWhitespace(PR_TRUE, PR_TRUE); - - nsCOMPtr document = do_QueryInterface(aContent->GetOwnerDoc()); - NS_ASSERTION(document, "The given node is not in document!"); - if (!document) - return; - - nsCOMPtr xblDocument; - if (aContent->IsInAnonymousSubtree()) - xblDocument = do_QueryInterface(document); - - nsCOMPtr refElms = do_CreateInstance(NS_ARRAY_CONTRACTID); - - while (!ids.IsEmpty()) { - nsAutoString id; - PRInt32 idLength = ids.FindChar(' '); - NS_ASSERTION(idLength != 0, - "Should not be 0 because of CompressWhitespace() call above"); - - if (idLength == kNotFound) { - id = ids; - ids.Truncate(); - } else { - id = Substring(ids, 0, idLength); - ids.Cut(0, idLength + 1); - } - - // If content is anonymous subtree then use "anonid" attribute to get - // elements, otherwise search elements in DOM by ID attribute. - nsCOMPtr refElement; - if (xblDocument) { - nsCOMPtr elm = - do_QueryInterface(aContent->GetBindingParent()); - xblDocument->GetAnonymousElementByAttribute(elm, - NS_LITERAL_STRING("anonid"), - id, - getter_AddRefs(refElement)); - } else { - document->GetElementById(id, getter_AddRefs(refElement)); - } - - if (!refElement) - continue; - - refElms->AppendElement(refElement, PR_FALSE); - } - - NS_ADDREF(*aRefElements = refElms); - return; -} - void nsCoreUtils::GetElementsHavingIDRefsAttr(nsIContent *aRootContent, nsIContent *aContent, @@ -1165,3 +1103,74 @@ nsAccessibleDOMStringList::Contains(const nsAString& aString, PRBool *aResult) return NS_OK; } + + +//////////////////////////////////////////////////////////////////////////////// +// IDRefsIterator +//////////////////////////////////////////////////////////////////////////////// + +IDRefsIterator::IDRefsIterator(nsIContent* aContent, nsIAtom* aIDRefsAttr) : + mCurrIdx(0) +{ + if (!aContent->IsInDoc() || + !aContent->GetAttr(kNameSpaceID_None, aIDRefsAttr, mIDs)) + return; + + if (aContent->IsInAnonymousSubtree()) { + mXBLDocument = do_QueryInterface(aContent->GetOwnerDoc()); + mBindingParent = do_QueryInterface(aContent->GetBindingParent()); + } else { + mDocument = aContent->GetOwnerDoc(); + } +} + +const nsDependentSubstring +IDRefsIterator::NextID() +{ + for (; mCurrIdx < mIDs.Length(); mCurrIdx++) { + if (!NS_IsAsciiWhitespace(mIDs[mCurrIdx])) + break; + } + + if (mCurrIdx >= mIDs.Length()) + return nsDependentSubstring(); + + nsAString::index_type idStartIdx = mCurrIdx; + while (++mCurrIdx < mIDs.Length()) { + if (NS_IsAsciiWhitespace(mIDs[mCurrIdx])) + break; + } + + return Substring(mIDs, idStartIdx, mCurrIdx++ - idStartIdx); +} + +nsIContent* +IDRefsIterator::NextElem() +{ + while (true) { + const nsDependentSubstring id = NextID(); + if (id.IsEmpty()) + break; + + if (mXBLDocument) { + // If content is anonymous subtree then use "anonid" attribute to get + // elements, otherwise search elements in DOM by ID attribute. + + nsCOMPtr refElm; + mXBLDocument->GetAnonymousElementByAttribute(mBindingParent, + NS_LITERAL_STRING("anonid"), + id, + getter_AddRefs(refElm)); + nsCOMPtr refContent = do_QueryInterface(refElm); + if (refContent) + return refContent; + + } else { + nsIContent* refContent = mDocument->GetElementById(id); + if (refContent) + return refContent; + } + } + + return nsnull; +} diff --git a/accessible/src/base/nsCoreUtils.h b/accessible/src/base/nsCoreUtils.h index 22ed47970401..bcdb9764e2fb 100644 --- a/accessible/src/base/nsCoreUtils.h +++ b/accessible/src/base/nsCoreUtils.h @@ -41,6 +41,7 @@ #include "nsAccessibilityAtoms.h" +#include "nsIDOMDocumentXBL.h" #include "nsIDOMNode.h" #include "nsIContent.h" #include "nsIBoxObject.h" @@ -304,17 +305,6 @@ public: static void GetLanguageFor(nsIContent *aContent, nsIContent *aRootContent, nsAString& aLanguage); - /** - * Return the array of elements the given node is referred to by its - * IDRefs attribute. - * - * @param aContent [in] the given node - * @param aAttr [in] IDRefs attribute on the given node - * @param aRefElements [out] result array of elements - */ - static void GetElementsByIDRefsAttr(nsIContent *aContent, nsIAtom *aAttr, - nsIArray **aRefElements); - /** * Return the array of elements having IDRefs that points to the given node. * @@ -515,5 +505,34 @@ private: nsTArray mNames; }; +/** + * Used to iterate through IDs or elements pointed by IDRefs attribute. Note, + * any method used to iterate through IDs or elements moves iterator to next + * position. + */ +class IDRefsIterator +{ +public: + IDRefsIterator(nsIContent* aContent, nsIAtom* aIDRefsAttr); + + /** + * Return next ID. + */ + const nsDependentSubstring NextID(); + + /** + * Return next element. + */ + nsIContent* NextElem(); + +private: + nsString mIDs; + nsAString::index_type mCurrIdx; + + nsIDocument* mDocument; + nsCOMPtr mXBLDocument; + nsCOMPtr mBindingParent; +}; + #endif diff --git a/accessible/src/base/nsRelUtils.cpp b/accessible/src/base/nsRelUtils.cpp index f272c4ded59f..7ca8a258f9e4 100644 --- a/accessible/src/base/nsRelUtils.cpp +++ b/accessible/src/base/nsRelUtils.cpp @@ -134,27 +134,16 @@ nsRelUtils::AddTargetFromIDRefsAttr(PRUint32 aRelationType, nsIAccessibleRelation **aRelation, nsIContent *aContent, nsIAtom *aAttr) { - nsCOMPtr refElms; - nsCoreUtils::GetElementsByIDRefsAttr(aContent, aAttr, getter_AddRefs(refElms)); + nsresult rv = NS_OK_NO_RELATION_TARGET; - if (!refElms) - return NS_OK_NO_RELATION_TARGET; - - PRUint32 count = 0; - nsresult rv = refElms->GetLength(&count); - if (NS_FAILED(rv) || count == 0) - return NS_OK_NO_RELATION_TARGET; - - nsCOMPtr content; - for (PRUint32 idx = 0; idx < count; idx++) { - content = do_QueryElementAt(refElms, idx, &rv); - NS_ENSURE_SUCCESS(rv, rv); - - rv = AddTargetFromContent(aRelationType, aRelation, content); + nsIContent* refElm = nsnull; + IDRefsIterator iter(aContent, aAttr); + while ((refElm = iter.NextElem())) { + rv = AddTargetFromContent(aRelationType, aRelation, refElm); NS_ENSURE_SUCCESS(rv, rv); } - return NS_OK; + return rv; } nsresult diff --git a/accessible/src/base/nsTextEquivUtils.cpp b/accessible/src/base/nsTextEquivUtils.cpp index 0abdb8073c48..48dcc15f7266 100644 --- a/accessible/src/base/nsTextEquivUtils.cpp +++ b/accessible/src/base/nsTextEquivUtils.cpp @@ -92,26 +92,14 @@ nsTextEquivUtils::GetTextEquivFromIDRefs(nsAccessible *aAccessible, if (!content) return NS_OK; - nsCOMPtr refElms; - nsCoreUtils::GetElementsByIDRefsAttr(content, aIDRefsAttr, - getter_AddRefs(refElms)); - - if (!refElms) - return NS_OK; - - PRUint32 count = 0; - nsresult rv = refElms->GetLength(&count); - NS_ENSURE_SUCCESS(rv, rv); - - nsCOMPtr refContent; - for (PRUint32 idx = 0; idx < count; idx++) { - refContent = do_QueryElementAt(refElms, idx, &rv); - NS_ENSURE_SUCCESS(rv, rv); - + nsIContent* refContent = nsnull; + IDRefsIterator iter(content, aIDRefsAttr); + while ((refContent = iter.NextElem())) { if (!aTextEquiv.IsEmpty()) aTextEquiv += ' '; - rv = AppendTextEquivFromContent(aAccessible, refContent, &aTextEquiv); + nsresult rv = AppendTextEquivFromContent(aAccessible, refContent, + &aTextEquiv); NS_ENSURE_SUCCESS(rv, rv); } diff --git a/accessible/src/html/nsHTMLTableAccessible.cpp b/accessible/src/html/nsHTMLTableAccessible.cpp index a72dbc63fa66..50d1da285bad 100644 --- a/accessible/src/html/nsHTMLTableAccessible.cpp +++ b/accessible/src/html/nsHTMLTableAccessible.cpp @@ -308,34 +308,27 @@ nsHTMLTableCellAccessible::GetHeaderCells(PRInt32 aRowOrColumnHeaderCell, nsIArray **aHeaderCells) { // Get header cells from @header attribute. - nsCOMPtr headerCellElms; - nsCoreUtils::GetElementsByIDRefsAttr(mContent, nsAccessibilityAtoms::headers, - getter_AddRefs(headerCellElms)); - - if (headerCellElms) { + IDRefsIterator iter(mContent, nsAccessibilityAtoms::headers); + nsIContent* headerCellElm = iter.NextElem(); + if (headerCellElm) { nsresult rv = NS_OK; nsCOMPtr headerCells = do_CreateInstance(NS_ARRAY_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, rv); - PRUint32 count = 0; - rv = headerCellElms->GetLength(&count); - if (NS_SUCCEEDED(rv) && count > 0) { - nsCOMPtr headerCellContent; - for (PRUint32 idx = 0; idx < count; idx++) { - headerCellContent = do_QueryElementAt(headerCellElms, idx, &rv); - nsAccessible *headerCell = - GetAccService()->GetAccessibleInWeakShell(headerCellContent, mWeakShell); + do { + nsAccessible* headerCell = + GetAccService()->GetAccessibleInWeakShell(headerCellElm, mWeakShell); - if (headerCell && - (aRowOrColumnHeaderCell == nsAccUtils::eRowHeaderCells && - headerCell->Role() == nsIAccessibleRole::ROLE_ROWHEADER || - aRowOrColumnHeaderCell == nsAccUtils::eColumnHeaderCells && - headerCell->Role() == nsIAccessibleRole::ROLE_COLUMNHEADER)) - headerCells->AppendElement(static_cast(headerCell), - PR_FALSE); + if (headerCell && + (aRowOrColumnHeaderCell == nsAccUtils::eRowHeaderCells && + headerCell->Role() == nsIAccessibleRole::ROLE_ROWHEADER || + aRowOrColumnHeaderCell == nsAccUtils::eColumnHeaderCells && + headerCell->Role() == nsIAccessibleRole::ROLE_COLUMNHEADER)) { + headerCells->AppendElement(static_cast(headerCell), + PR_FALSE); } - } + } while ((headerCellElm = iter.NextElem())); NS_ADDREF(*aHeaderCells = headerCells); return NS_OK;