From 1911fb04f0d145437ca790ca77bc6f19087c83af Mon Sep 17 00:00:00 2001 From: James Teh Date: Mon, 25 Mar 2019 05:04:29 +0000 Subject: [PATCH] Bug 1530931: Correctly handle retrieving a container accessible for a shadow root. r=eeejay This can happen, for example, when GetAccessibleOrContainer is called within SelectionManager::ProcessSelectionChanged due to focusing a direct child of a shadow root. In this case, the common ancestor is the shadow root itself. Previously, we returned null in this case because GetFlattenedTreeParent doesn't work on the shadow root itself. Now, we check if the given node is the shadow root, and if so, we use the shadow host instead. This prevents the "We must reach document accessible implementing text interface!" assertion in SelectionManager::ProcessSelectionChanged when a direct child of a shadow root gets focus. Differential Revision: https://phabricator.services.mozilla.com/D21349 --HG-- extra : moz-landing-system : lando --- accessible/generic/DocAccessible.cpp | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/accessible/generic/DocAccessible.cpp b/accessible/generic/DocAccessible.cpp index 3a4a657fcab6..4367a1ec4d4f 100644 --- a/accessible/generic/DocAccessible.cpp +++ b/accessible/generic/DocAccessible.cpp @@ -1130,10 +1130,28 @@ Accessible* DocAccessible::GetAccessibleByUniqueIDInSubtree(void* aUniqueID) { Accessible* DocAccessible::GetAccessibleOrContainer(nsINode* aNode, int aARIAHiddenFlag) const { - if (!aNode || !aNode->GetComposedDoc()) return nullptr; + if (!aNode || !aNode->GetComposedDoc()) { + return nullptr; + } - for (nsINode* currNode = aNode; currNode; - currNode = currNode->GetFlattenedTreeParentNode()) { + nsINode* currNode = nullptr; + if (aNode->IsShadowRoot()) { + // This can happen, for example, when called within + // SelectionManager::ProcessSelectionChanged due to focusing a direct + // child of a shadow root. + // GetFlattenedTreeParent works on children of a shadow root, but not the + // shadow root itself. + const dom::ShadowRoot* shadowRoot = dom::ShadowRoot::FromNode(aNode); + currNode = shadowRoot->GetHost(); + if (!currNode) { + return nullptr; + } + } else { + currNode = aNode; + } + + MOZ_ASSERT(currNode); + for (; currNode; currNode = currNode->GetFlattenedTreeParentNode()) { // No container if is inside of aria-hidden subtree. if (aARIAHiddenFlag == eNoContainerIfARIAHidden && currNode->IsElement() && aria::HasDefinedARIAHidden(currNode->AsElement())) {