Bug 1122846 - aria-owns attribute causes Firefox to hang, r=davidb

This commit is contained in:
Alexander Surkov 2015-01-20 16:16:08 -05:00
parent a07b4d2d32
commit 09724cb4bf
5 changed files with 119 additions and 7 deletions

View File

@ -331,6 +331,64 @@ IDRefsIterator::Next()
}
////////////////////////////////////////////////////////////////////////////////
// ARIAOwnedByIterator
////////////////////////////////////////////////////////////////////////////////
ARIAOwnedByIterator::ARIAOwnedByIterator(const Accessible* aDependent) :
RelatedAccIterator(aDependent->Document(), aDependent->GetContent(),
nsGkAtoms::aria_owns), mDependent(aDependent)
{
}
Accessible*
ARIAOwnedByIterator::Next()
{
Accessible* owner = RelatedAccIterator::Next();
Accessible* cur = owner;
while (cur) {
if (cur == mDependent)
return Next(); // owner cannot be a child of dependent.
if (cur->IsDoc())
break; // don't cross document boundaries
cur = cur->Parent();
}
return owner;
}
////////////////////////////////////////////////////////////////////////////////
// ARIAOwnsIterator
////////////////////////////////////////////////////////////////////////////////
ARIAOwnsIterator::ARIAOwnsIterator(const Accessible* aOwner) :
mIter(aOwner->Document(), aOwner->GetContent(), nsGkAtoms::aria_owns),
mOwner(aOwner)
{
}
Accessible*
ARIAOwnsIterator::Next()
{
Accessible* child = mIter.Next();
const Accessible* cur = mOwner;
while (cur) {
if (cur == child)
return Next(); // cannot own its own parent
if (cur->IsDoc())
break; // don't cross document boundaries
cur = cur->Parent();
}
return child;
}
////////////////////////////////////////////////////////////////////////////////
// SingleAccIterator
////////////////////////////////////////////////////////////////////////////////

View File

@ -247,6 +247,48 @@ private:
nsAString::index_type mCurrIdx;
};
/**
* Iterates over related accessible referred by aria-owns.
*/
class ARIAOwnedByIterator MOZ_FINAL : public RelatedAccIterator
{
public:
explicit ARIAOwnedByIterator(const Accessible* aDependent);
virtual ~ARIAOwnedByIterator() { }
virtual Accessible* Next() MOZ_OVERRIDE;
private:
ARIAOwnedByIterator() = delete;
ARIAOwnedByIterator(const ARIAOwnedByIterator&) = delete;
ARIAOwnedByIterator& operator = (const ARIAOwnedByIterator&) = delete;
const Accessible* mDependent;
};
/**
* Iterates over related accessible referred by aria-owns.
*/
class ARIAOwnsIterator MOZ_FINAL : public AccIterable
{
public:
explicit ARIAOwnsIterator(const Accessible* aOwner);
virtual ~ARIAOwnsIterator() { }
virtual Accessible* Next() MOZ_OVERRIDE;
private:
ARIAOwnsIterator() = delete;
ARIAOwnsIterator(const ARIAOwnsIterator&) = delete;
ARIAOwnsIterator& operator = (const ARIAOwnsIterator&) = delete;
IDRefsIterator mIter;
const Accessible* mOwner;
};
/**
* Iterator that points to a single accessible returning it on the first call
* to Next().

View File

@ -324,9 +324,7 @@ FocusManager::ProcessFocusEvent(AccEvent* aEvent)
if (!tryOwnsParent)
break;
RelatedAccIterator iter(child->Document(), child->GetContent(),
nsGkAtoms::aria_owns);
parent = iter.Next();
parent = ARIAOwnedByIterator(child).Next();
tryOwnsParent = false;
}

View File

@ -1281,7 +1281,7 @@ Accessible::Value(nsString& aValue)
Accessible* option = CurrentItem();
if (!option) {
Accessible* listbox = nullptr;
IDRefsIterator iter(mDoc, mContent, nsGkAtoms::aria_owns);
ARIAOwnsIterator iter(this);
while ((listbox = iter.Next()) && !listbox->IsListControl());
if (!listbox) {
@ -1559,8 +1559,7 @@ Accessible::RelationByType(RelationType aType)
}
case RelationType::NODE_CHILD_OF: {
Relation rel(new RelatedAccIterator(Document(), mContent,
nsGkAtoms::aria_owns));
Relation rel(new ARIAOwnedByIterator(this));
// This is an ARIA tree or treegrid that doesn't use owns, so we need to
// get the parent the hard way.
@ -1590,7 +1589,7 @@ Accessible::RelationByType(RelationType aType)
}
case RelationType::NODE_PARENT_OF: {
Relation rel(new IDRefsIterator(mDoc, mContent, nsGkAtoms::aria_owns));
Relation rel(new ARIAOwnsIterator(this));
// ARIA tree or treegrid can do the hierarchy by @aria-level, ARIA trees
// also can be organized by groups.

View File

@ -74,6 +74,15 @@
testRelation("treeitem1", RELATION_NODE_CHILD_OF, "tree");
testRelation("treeitem2", RELATION_NODE_CHILD_OF, "tree");
// aria-owns, bad relations
testRelation("ariaowns_container", RELATION_NODE_CHILD_OF, null);
testRelation("ariaowns_self", RELATION_NODE_CHILD_OF, null);
testRelation("ariaowns_uncle", RELATION_NODE_CHILD_OF, "ariaowns_self");
testRelation("ariaowns_container", RELATION_NODE_PARENT_OF, null);
testRelation("ariaowns_self", RELATION_NODE_PARENT_OF, "ariaowns_uncle");
testRelation("ariaowns_uncle", RELATION_NODE_PARENT_OF, null);
// 'node child of' relation for outlineitem role
testRelation("treeitem3", RELATION_NODE_CHILD_OF, "tree");
testRelation("treeitem4", RELATION_NODE_CHILD_OF, "tree");
@ -310,6 +319,12 @@
</div>
</div>
<div id="ariaowns_container">
<div id="ariaowns_self"
aria-owns="aria_ownscontainer ariaowns_self ariaowns_uncle"></div>
</div>
<div id="ariaowns_uncle"></div>
<div aria-owns="simplegrid-ownrow" role="grid" id="simplegrid">
<div role="row" id="simplegrid-row1" aria-level="1">
<div role="gridcell">cell 1,1</div>