Bug 1353094 - simplify the logic of accessible subtrees removal, r=davidb

This commit is contained in:
Alexander Surkov
2017-04-25 14:02:41 -04:00
parent 15127eb85a
commit 083e10ff0a
6 changed files with 50 additions and 65 deletions

View File

@@ -676,7 +676,7 @@ NotificationController::WillRefresh(mozilla::TimeStamp aTime)
}
#endif
mDocument->ContentRemoved(containerElm, textNode);
mDocument->ContentRemoved(textAcc);
continue;
}

View File

@@ -52,6 +52,18 @@ TreeWalker::
MOZ_COUNT_CTOR(TreeWalker);
}
TreeWalker::
TreeWalker(DocAccessible* aDocument, nsIContent* aAnchorNode) :
mDoc(aDocument), mContext(nullptr), mAnchorNode(aAnchorNode),
mARIAOwnsIdx(0),
mChildFilter(nsIContent::eSkipPlaceholderContent | nsIContent::eAllChildren),
mFlags(eWalkCache),
mPhase(eAtStart)
{
MOZ_ASSERT(aAnchorNode, "No anchor node for the accessible tree walker");
MOZ_COUNT_CTOR(TreeWalker);
}
TreeWalker::~TreeWalker()
{
MOZ_COUNT_DTOR(TreeWalker);

View File

@@ -47,6 +47,11 @@ public:
*/
TreeWalker(Accessible* aContext, nsIContent* aAnchorNode, uint32_t aFlags = eWalkCache);
/**
* Navigates the accessible children within the anchor node subtree.
*/
TreeWalker(DocAccessible* aDocument, nsIContent* aAnchorNode);
~TreeWalker();
/**

View File

@@ -524,7 +524,7 @@ nsAccessibilityService::DeckPanelSwitched(nsIPresShell* aPresShell,
}
#endif
document->ContentRemoved(aDeckNode, panelNode);
document->ContentRemoved(panelNode);
}
if (aCurrentBoxFrame) {
@@ -582,26 +582,7 @@ nsAccessibilityService::ContentRemoved(nsIPresShell* aPresShell,
#endif
if (document) {
// Flatten hierarchy may be broken at this point so we cannot get a true
// container by traversing up the DOM tree. Find a parent of first accessible
// from the subtree of the given DOM node, that'll be a container. If no
// accessibles in subtree then we don't care about the change.
Accessible* child = document->GetAccessible(aChildNode);
if (!child) {
Accessible* container = document->GetContainerAccessible(aChildNode);
a11y::TreeWalker walker(container ? container : document, aChildNode,
a11y::TreeWalker::eWalkCache);
child = walker.Next();
}
if (child) {
MOZ_DIAGNOSTIC_ASSERT(child->Parent(), "Unattached accessible from tree");
document->ContentRemoved(child->Parent(), aChildNode);
#ifdef A11Y_LOG
if (logging::IsEnabled(logging::eTree))
logging::AccessibleNNode("real container", child->Parent());
#endif
}
document->ContentRemoved(aChildNode);
}
#ifdef A11Y_LOG

View File

@@ -1170,10 +1170,7 @@ DocAccessible::ContentRemoved(nsIDocument* aDocument,
// This one and content removal notification from layout may result in
// double processing of same subtrees. If it pops up in profiling, then
// consider reusing a document node cache to reject these notifications early.
Accessible* container = GetAccessibleOrContainer(aContainerNode);
if (container) {
UpdateTreeOnRemoval(container, aChildNode);
}
ContentRemoved(aChildNode);
}
void
@@ -1382,7 +1379,7 @@ DocAccessible::RecreateAccessible(nsIContent* aContent)
// should be coalesced with normal show/hide events.
nsIContent* parent = aContent->GetFlattenedTreeParent();
ContentRemoved(parent, aContent);
ContentRemoved(aContent);
ContentInserted(parent, aContent, aContent->GetNextSibling());
}
@@ -1972,35 +1969,38 @@ DocAccessible::FireEventsOnInsertion(Accessible* aContainer)
}
void
DocAccessible::UpdateTreeOnRemoval(Accessible* aContainer, nsIContent* aChildNode)
DocAccessible::ContentRemoved(Accessible* aContent)
{
// If child node is not accessible then look for its accessible children.
Accessible* child = GetAccessible(aChildNode);
MOZ_DIAGNOSTIC_ASSERT(aContent->Parent(), "Unattached accessible from tree");
#ifdef A11Y_LOG
logging::TreeInfo("process content removal", 0,
"container", aContainer, "child", aChildNode);
"container", aContent->Parent(), "child", aContent, nullptr);
#endif
TreeMutation mt(aContainer);
if (child) {
mt.BeforeRemoval(child);
MOZ_ASSERT(aContainer == child->Parent(), "Wrong parent");
aContainer->RemoveChild(child);
UncacheChildrenInSubtree(child);
mt.Done();
return;
}
TreeWalker walker(aContainer, aChildNode, TreeWalker::eWalkCache);
while (Accessible* child = walker.Next()) {
mt.BeforeRemoval(child);
MOZ_ASSERT(aContainer == child->Parent(), "Wrong parent");
aContainer->RemoveChild(child);
UncacheChildrenInSubtree(child);
}
TreeMutation mt(aContent->Parent());
mt.BeforeRemoval(aContent);
aContent->Parent()->RemoveChild(aContent);
UncacheChildrenInSubtree(aContent);
mt.Done();
}
void
DocAccessible::ContentRemoved(nsIContent* aContentNode)
{
// If child node is not accessible then look for its accessible children.
Accessible* acc = GetAccessible(aContentNode);
if (acc) {
ContentRemoved(acc);
}
else {
TreeWalker walker(this, aContentNode);
while (Accessible* acc = walker.Next()) {
ContentRemoved(acc);
}
}
}
bool
DocAccessible::RelocateARIAOwnedIfNeeded(nsIContent* aElement)
{
@@ -2051,7 +2051,7 @@ DocAccessible::ValidateARIAOwned()
// If DOM node doesn't have a frame anymore then shutdown its accessible.
if (child->Parent() && !child->GetFrame()) {
UpdateTreeOnRemoval(child->Parent(), child->GetContent());
ContentRemoved(child);
children->RemoveElementAt(idx);
idx--;
continue;

View File

@@ -342,18 +342,10 @@ public:
nsIContent* aEndChildNode);
/**
* Notify the document accessible that content was removed.
* Update the tree on content removal.
*/
void ContentRemoved(Accessible* aContainer, nsIContent* aChildNode)
{
// Update the whole tree of this document accessible when the container is
// null (document element is removed).
UpdateTreeOnRemoval((aContainer ? aContainer : this), aChildNode);
}
void ContentRemoved(nsIContent* aContainerNode, nsIContent* aChildNode)
{
ContentRemoved(AccessibleOrTrueContainer(aContainerNode), aChildNode);
}
void ContentRemoved(Accessible* aContent);
void ContentRemoved(nsIContent* aContentNode);
/**
* Updates accessible tree when rendered text is changed.
@@ -512,11 +504,6 @@ protected:
*/
void ProcessInvalidationList();
/**
* Update the accessible tree for content removal.
*/
void UpdateTreeOnRemoval(Accessible* aContainer, nsIContent* aChildNode);
/**
* Validates all aria-owns connections and updates the tree accordingly.
*/