Bug 1506514 - Don't create accessibles for unselected deck panel descendants. r=Jamie

Differential Revision: https://phabricator.services.mozilla.com/D31656

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Eitan Isaacson 2019-05-20 15:54:56 +00:00
parent bc1c818a3b
commit 661bd00c42
5 changed files with 75 additions and 14 deletions

View File

@ -751,8 +751,8 @@ void NotificationController::WillRefresh(mozilla::TimeStamp aTime) {
MOZ_ASSERT(mDocument->AccessibleOrTrueContainer(containerNode),
"Text node having rendered text hasn't accessible document!");
Accessible* container = mDocument->AccessibleOrTrueContainer(
containerNode, DocAccessible::eNoContainerIfARIAHidden);
Accessible* container =
mDocument->AccessibleOrTrueContainer(containerNode, true);
if (container) {
nsTArray<nsCOMPtr<nsIContent>>* list =
mContentInsertions.LookupOrAdd(container);

View File

@ -23,10 +23,10 @@ namespace mozilla {
namespace a11y {
inline Accessible* DocAccessible::AccessibleOrTrueContainer(
nsINode* aNode, int aIgnoreARIAHidden) const {
nsINode* aNode, bool aNoContainerIfPruned) const {
// HTML comboboxes have no-content list accessible as an intermediate
// containing all options.
Accessible* container = GetAccessibleOrContainer(aNode, aIgnoreARIAHidden);
Accessible* container = GetAccessibleOrContainer(aNode, aNoContainerIfPruned);
if (container && container->IsHTMLCombobox()) {
return container->FirstChild();
}

View File

@ -1132,8 +1132,8 @@ Accessible* DocAccessible::GetAccessibleByUniqueIDInSubtree(void* aUniqueID) {
return nullptr;
}
Accessible* DocAccessible::GetAccessibleOrContainer(nsINode* aNode,
int aARIAHiddenFlag) const {
Accessible* DocAccessible::GetAccessibleOrContainer(
nsINode* aNode, bool aNoContainerIfPruned) const {
if (!aNode || !aNode->GetComposedDoc()) {
return nullptr;
}
@ -1157,11 +1157,26 @@ Accessible* DocAccessible::GetAccessibleOrContainer(nsINode* aNode,
MOZ_ASSERT(currNode);
for (; currNode; currNode = currNode->GetFlattenedTreeParentNode()) {
// No container if is inside of aria-hidden subtree.
if (aARIAHiddenFlag == eNoContainerIfARIAHidden && currNode->IsElement() &&
if (aNoContainerIfPruned && currNode->IsElement() &&
aria::HasDefinedARIAHidden(currNode->AsElement())) {
return nullptr;
}
// Check if node is in an unselected deck panel
if (aNoContainerIfPruned && currNode->IsXULElement()) {
if (nsIFrame* frame = currNode->AsContent()->GetPrimaryFrame()) {
nsDeckFrame* deckFrame = do_QueryFrame(frame->GetParent());
if (deckFrame && deckFrame->GetSelectedBox() != frame) {
// If deck is not a <tabpanels>, return null
nsIContent* parentFrameContent = deckFrame->GetContent();
if (!parentFrameContent ||
!parentFrameContent->IsXULElement(nsGkAtoms::tabpanels)) {
return nullptr;
}
}
}
}
if (Accessible* accessible = GetAccessible(currNode)) {
return accessible;
}
@ -1666,8 +1681,7 @@ bool InsertIterator::Next() {
// what means there's no container. Ignore the insertion too.
nsIContent* prevNode = mNodes->SafeElementAt(mNodesIdx - 1);
nsIContent* node = mNodes->ElementAt(mNodesIdx++);
Accessible* container = Document()->AccessibleOrTrueContainer(
node, DocAccessible::eNoContainerIfARIAHidden);
Accessible* container = Document()->AccessibleOrTrueContainer(node, true);
if (container != Context()) {
continue;
}

View File

@ -284,11 +284,12 @@ class DocAccessible : public HyperTextAccessibleWrap,
/**
* Return an accessible for the given DOM node or container accessible if
* the node is not accessible.
* the node is not accessible. If aNoContainerIfPruned is true it will return
* null if the node is in a pruned subtree (eg. aria-hidden or unselected deck
* panel)
*/
enum { eIgnoreARIAHidden = 0, eNoContainerIfARIAHidden = 1 };
Accessible* GetAccessibleOrContainer(
nsINode* aNode, int aARIAHiddenFlag = eIgnoreARIAHidden) const;
Accessible* GetAccessibleOrContainer(nsINode* aNode,
bool aNoContainerIfPruned = false) const;
/**
* Return a container accessible for the given DOM node.
@ -302,7 +303,7 @@ class DocAccessible : public HyperTextAccessibleWrap,
* container for it.
*/
Accessible* AccessibleOrTrueContainer(
nsINode* aNode, int aARIAHiddenFlag = eIgnoreARIAHidden) const;
nsINode* aNode, bool aNoContainerIfPruned = false) const;
/**
* Return an accessible for the given node or its first accessible descendant.

View File

@ -64,10 +64,55 @@
}
}
function showDeckPanel(aContainerID, aPanelID)
{
this.container = getAccessible(aContainerID);
this.deckNode = getNode(aPanelID);
var tree =
{ GROUPING: [ // role="group"
{ GROUPING: [ // grouping of panel 2
{ PUSHBUTTON: [] } // push button in panel 2
] }
] };
this.unexpectedEventSeq = [
new invokerChecker(EVENT_REORDER, this.container)
];
this.invoke = function showDeckPanel_invoke()
{
// This stops the refreh driver from doing its regular ticks, and leaves
// us in control. 100 is an arbitrary positive number to advance the clock
// it is not checked or used anywhere.
window.windowUtils.advanceTimeAndRefresh(100);
testAccessibleTree(this.container, tree);
this.deckNode.style.display = "-moz-box";
// This flushes our DOM mutations and forces any pending mutation events.
window.windowUtils.advanceTimeAndRefresh(100);
}
this.finalCheck = function showDeckPanel_finalCheck()
{
testAccessibleTree(this.container, tree);
// Return to regular refresh driver ticks.
window.windowUtils.restoreNormalRefresh();
}
this.getID = function showDeckPanel_getID()
{
return "show deck panel";
}
}
var gQueue = null;
function doTest()
{
gQueue = new eventQueue();
gQueue.push(new showDeckPanel("container", "hidden"));
gQueue.push(new switchDeckPanel("container", "deck"));
gQueue.invoke(); // will call SimpleTest.finish();
}
@ -99,6 +144,7 @@
<groupbox>
<button label="This is the second page"/>
</groupbox>
<hbox id="hidden" style="display: none;"><label>This is the third page</label></hbox>
</deck>
</vbox>