Skip to content

Commit

Permalink
Backed out 3 changesets (bug 1722396) for Linting failure in accessib…
Browse files Browse the repository at this point in the history
…le/tests/browser/mac/browser_aria_expanded.js. CLOSED TREE

Backed out changeset 86fc719a7a94 (bug 1722396)
Backed out changeset 02dea4423d5d (bug 1722396)
Backed out changeset 22f85fd34b27 (bug 1722396)
  • Loading branch information
dgluca committed Aug 2, 2021
1 parent ae14773 commit 41530b2
Show file tree
Hide file tree
Showing 11 changed files with 497 additions and 401 deletions.
404 changes: 384 additions & 20 deletions accessible/generic/DocAccessible.cpp

Large diffs are not rendered by default.

27 changes: 25 additions & 2 deletions accessible/generic/DocAccessible.h
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,25 @@ class DocAccessible : public HyperTextAccessibleWrap,
bool UpdateAccessibleOnAttrChange(mozilla::dom::Element* aElement,
nsAtom* aAttribute);

/**
* Fire accessible events when attribute is changed.
*
* @param aAccessible [in] accessible the DOM attribute is changed for
* @param aNameSpaceID [in] namespace of changed attribute
* @param aAttribute [in] changed attribute
* @param aModType [in] modification type (changed/added/removed)
*/
void AttributeChangedImpl(LocalAccessible* aAccessible, int32_t aNameSpaceID,
nsAtom* aAttribute, int32_t aModType);

/**
* Fire accessible events when ARIA attribute is changed.
*
* @param aAccessible [in] accesislbe the DOM attribute is changed for
* @param aAttribute [in] changed attribute
*/
void ARIAAttributeChanged(LocalAccessible* aAccessible, nsAtom* aAttribute);

/**
* Process ARIA active-descendant attribute change.
*/
Expand Down Expand Up @@ -616,9 +635,13 @@ class DocAccessible : public HyperTextAccessibleWrap,
* A generic state (see items below) before the attribute value was changed.
* @see AttributeWillChange and AttributeChanged notifications.
*/
union {
// ARIA attribute value
const nsAtom* mARIAAttrOldValue;

// Previous state bits before attribute change
uint64_t mPrevStateBits;
// Previous state bits before attribute change
uint64_t mPrevStateBits;
};

nsTArray<RefPtr<DocAccessible>> mChildDocuments;

Expand Down
224 changes: 0 additions & 224 deletions accessible/generic/LocalAccessible.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
#include "TableAccessible.h"
#include "TableCellAccessible.h"
#include "TreeWalker.h"
#include "HTMLElementAccessibles.h"

#include "nsIDOMXULButtonElement.h"
#include "nsIDOMXULSelectCntrlEl.h"
Expand Down Expand Up @@ -83,7 +82,6 @@
#include "mozilla/dom/KeyboardEventBinding.h"
#include "mozilla/dom/TreeWalker.h"
#include "mozilla/dom/UserActivation.h"
#include "mozilla/dom/MutationEventBinding.h"

using namespace mozilla;
using namespace mozilla::a11y;
Expand Down Expand Up @@ -1133,228 +1131,6 @@ already_AddRefed<AccAttributes> LocalAccessible::NativeAttributes() {
return attributes.forget();
}

bool LocalAccessible::AttributeChangesState(nsAtom* aAttribute) {
return aAttribute == nsGkAtoms::aria_disabled ||
aAttribute == nsGkAtoms::disabled ||
aAttribute == nsGkAtoms::tabindex ||
aAttribute == nsGkAtoms::aria_required ||
aAttribute == nsGkAtoms::aria_invalid ||
aAttribute == nsGkAtoms::aria_expanded ||
aAttribute == nsGkAtoms::aria_checked ||
(aAttribute == nsGkAtoms::aria_pressed && IsButton()) ||
aAttribute == nsGkAtoms::aria_readonly ||
aAttribute == nsGkAtoms::aria_current ||
aAttribute == nsGkAtoms::aria_haspopup ||
aAttribute == nsGkAtoms::aria_busy ||
aAttribute == nsGkAtoms::aria_multiline ||
aAttribute == nsGkAtoms::aria_selected ||
(aAttribute == nsGkAtoms::selected && mContent->IsXULElement()) ||
aAttribute == nsGkAtoms::contenteditable ||
(aAttribute == nsGkAtoms::href && IsHTMLLink());
}

void LocalAccessible::DOMAttributeChanged(int32_t aNameSpaceID,
nsAtom* aAttribute, int32_t aModType,
const nsAttrValue* aOldValue,
uint64_t aOldState) {
// Fire accessible event after short timer, because we need to wait for
// DOM attribute & resulting layout to actually change. Otherwise,
// assistive technology will retrieve the wrong state/value/selection info.

// XXX todo
// We still need to handle special HTML cases here
// For example, if an <img>'s usemap attribute is modified
// Otherwise it may just be a state change, for example an object changing
// its visibility
//
// XXX todo: report aria state changes for "undefined" literal value changes
// filed as bug 472142
//
// XXX todo: invalidate accessible when aria state changes affect exposed
// role filed as bug 472143

if (AttributeChangesState(aAttribute)) {
uint64_t currState = State();
uint64_t diffState = currState ^ aOldState;
if (diffState) {
for (uint64_t state = 1; state <= states::LAST_ENTRY; state <<= 1) {
if (diffState & state) {
RefPtr<AccEvent> stateChangeEvent =
new AccStateChangeEvent(this, state, (currState & state));
mDoc->FireDelayedEvent(stateChangeEvent);
}
}
}
}

// When a details object has its open attribute changed
// we should fire a state-change event on the accessible of
// its main summary
if (aAttribute == nsGkAtoms::open) {
// FromDetails checks if the given accessible belongs to
// a details frame and also locates the accessible of its
// main summary.
if (HTMLSummaryAccessible* summaryAccessible =
HTMLSummaryAccessible::FromDetails(this)) {
RefPtr<AccEvent> expandedChangeEvent =
new AccStateChangeEvent(summaryAccessible, states::EXPANDED);
mDoc->FireDelayedEvent(expandedChangeEvent);
return;
}
}

// Check for namespaced ARIA attribute
if (aNameSpaceID == kNameSpaceID_None) {
// Check for hyphenated aria-foo property?
if (StringBeginsWith(nsDependentAtomString(aAttribute), u"aria-"_ns)) {
uint8_t attrFlags = aria::AttrCharacteristicsFor(aAttribute);
if (!(attrFlags & ATTR_BYPASSOBJ)) {
// For aria attributes like drag and drop changes we fire a generic
// attribute change event; at least until native API comes up with a
// more meaningful event.
RefPtr<AccEvent> event =
new AccObjectAttrChangedEvent(this, aAttribute);
mDoc->FireDelayedEvent(event);
}
}
}

dom::Element* elm = Elm();

// Fire text value change event whenever aria-valuetext is changed.
if (aAttribute == nsGkAtoms::aria_valuetext) {
mDoc->FireDelayedEvent(nsIAccessibleEvent::EVENT_TEXT_VALUE_CHANGE, this);
return;
}

// Fire numeric value change event when aria-valuenow is changed and
// aria-valuetext is empty
if (aAttribute == nsGkAtoms::aria_valuenow &&
(!elm->HasAttr(kNameSpaceID_None, nsGkAtoms::aria_valuetext) ||
elm->AttrValueIs(kNameSpaceID_None, nsGkAtoms::aria_valuetext,
nsGkAtoms::_empty, eCaseMatters))) {
mDoc->FireDelayedEvent(nsIAccessibleEvent::EVENT_VALUE_CHANGE, this);
return;
}

if (aAttribute == nsGkAtoms::aria_owns) {
mDoc->Controller()->ScheduleRelocation(this);
}

// Fire name change and description change events. XXX: it's not complete and
// dupes the code logic of accessible name and description calculation, we do
// that for performance reasons.
if (aAttribute == nsGkAtoms::aria_label) {
mDoc->FireDelayedEvent(nsIAccessibleEvent::EVENT_NAME_CHANGE, this);
return;
}

if (aAttribute == nsGkAtoms::aria_describedby) {
mDoc->FireDelayedEvent(nsIAccessibleEvent::EVENT_DESCRIPTION_CHANGE, this);
if (aModType == dom::MutationEvent_Binding::MODIFICATION ||
aModType == dom::MutationEvent_Binding::ADDITION) {
// The subtrees of the new aria-describedby targets might be used to
// compute the description for this. Therefore, we need to set
// the eHasDescriptionDependent flag on all Accessibles in these subtrees.
IDRefsIterator iter(mDoc, elm, nsGkAtoms::aria_describedby);
while (LocalAccessible* target = iter.Next()) {
Pivot pivot(target);
LocalAccInSameDocRule rule;
for (Accessible* anchor = target; anchor;
anchor = pivot.Next(anchor, rule)) {
LocalAccessible* acc = anchor->AsLocal();
MOZ_ASSERT(acc);
acc->mContextFlags |= eHasDescriptionDependent;
}
}
}
return;
}

if (aAttribute == nsGkAtoms::aria_labelledby &&
!elm->HasAttr(kNameSpaceID_None, nsGkAtoms::aria_label)) {
mDoc->FireDelayedEvent(nsIAccessibleEvent::EVENT_NAME_CHANGE, this);
if (aModType == dom::MutationEvent_Binding::MODIFICATION ||
aModType == dom::MutationEvent_Binding::ADDITION) {
// The subtrees of the new aria-labelledby targets might be used to
// compute the name for this. Therefore, we need to set
// the eHasNameDependent flag on all Accessibles in these subtrees.
IDRefsIterator iter(mDoc, elm, nsGkAtoms::aria_labelledby);
while (LocalAccessible* target = iter.Next()) {
Pivot pivot(target);
LocalAccInSameDocRule rule;
for (Accessible* anchor = target; anchor;
anchor = pivot.Next(anchor, rule)) {
LocalAccessible* acc = anchor->AsLocal();
MOZ_ASSERT(acc);
acc->mContextFlags |= eHasNameDependent;
}
}
}
return;
}

if (aAttribute == nsGkAtoms::alt &&
!elm->HasAttr(kNameSpaceID_None, nsGkAtoms::aria_label) &&
!elm->HasAttr(kNameSpaceID_None, nsGkAtoms::aria_labelledby)) {
mDoc->FireDelayedEvent(nsIAccessibleEvent::EVENT_NAME_CHANGE, this);
return;
}

if (aAttribute == nsGkAtoms::title) {
if (!elm->HasAttr(kNameSpaceID_None, nsGkAtoms::aria_label) &&
!elm->HasAttr(kNameSpaceID_None, nsGkAtoms::aria_labelledby) &&
!elm->HasAttr(kNameSpaceID_None, nsGkAtoms::alt)) {
mDoc->FireDelayedEvent(nsIAccessibleEvent::EVENT_NAME_CHANGE, this);
return;
}

if (!elm->HasAttr(kNameSpaceID_None, nsGkAtoms::aria_describedby)) {
mDoc->FireDelayedEvent(nsIAccessibleEvent::EVENT_DESCRIPTION_CHANGE,
this);
}

return;
}

// These attributes can change whether or not a table is a layout table.
// We currently cache that information on Mac, so we fire a
// EVENT_OBJECT_ATTRIBUTE_CHANGED, which Mac listens for, to invalidate.
if (IsTable() || IsTableRow() || IsTableCell()) {
if (aAttribute == nsGkAtoms::summary || aAttribute == nsGkAtoms::headers ||
aAttribute == nsGkAtoms::scope || aAttribute == nsGkAtoms::abbr) {
mDoc->FireDelayedEvent(nsIAccessibleEvent::EVENT_OBJECT_ATTRIBUTE_CHANGED,
this);
}
}

// ARIA or XUL selection
if ((mContent->IsXULElement() && aAttribute == nsGkAtoms::selected) ||
aAttribute == nsGkAtoms::aria_selected) {
LocalAccessible* widget = nsAccUtils::GetSelectableContainer(this, State());
if (widget) {
AccSelChangeEvent::SelChangeType selChangeType =
elm->AttrValueIs(aNameSpaceID, aAttribute, nsGkAtoms::_true,
eCaseMatters)
? AccSelChangeEvent::eSelectionAdd
: AccSelChangeEvent::eSelectionRemove;

RefPtr<AccEvent> event =
new AccSelChangeEvent(widget, this, selChangeType);
mDoc->FireDelayedEvent(event);
}

return;
}

if (aAttribute == nsGkAtoms::value) {
if (IsProgress()) {
mDoc->FireDelayedEvent(nsIAccessibleEvent::EVENT_VALUE_CHANGE, this);
}
return;
}
}

GroupPos LocalAccessible::GroupPosition() {
GroupPos groupPos;
if (!HasOwnContent()) return groupPos;
Expand Down
19 changes: 0 additions & 19 deletions accessible/generic/LocalAccessible.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@ struct nsRoleMapEntry;

class nsIFrame;

class nsAttrValue;

namespace mozilla::dom {
class Element;
}
Expand Down Expand Up @@ -931,23 +929,6 @@ class LocalAccessible : public nsISupports, public Accessible {
*/
virtual already_AddRefed<AccAttributes> NativeAttributes();

/**
* The given attribute has the potential of changing the accessible's state.
* This is used to capture the state before the attribute change and compare
* it with the state after.
*/
bool AttributeChangesState(nsAtom* aAttribute);

/**
* Notify accessible that a DOM attribute on its associated content has
* changed. This allows the accessible to update its state and emit any
* relevant events.
*/
virtual void DOMAttributeChanged(int32_t aNameSpaceID, nsAtom* aAttribute,
int32_t aModType,
const nsAttrValue* aOldValue,
uint64_t aOldState);

//////////////////////////////////////////////////////////////////////////////
// Initializing, cache and tree traverse methods

Expand Down
4 changes: 3 additions & 1 deletion accessible/tests/browser/mac/browser_aria_current.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,19 +31,21 @@ addAccessibleTask(
"Correct aria-current for #two"
);

let stateChanged = waitForEvent(EVENT_STATE_CHANGE, "one");
await SpecialPowers.spawn(browser, [], () => {
content.document
.getElementById("one")
.setAttribute("aria-current", "step");
});
await stateChanged;

is(
one.getAttributeValue("AXARIACurrent"),
"step",
"Correct aria-current for #one"
);

let stateChanged = waitForEvent(EVENT_STATE_CHANGE, "one");
stateChanged = waitForEvent(EVENT_STATE_CHANGE, "one");
await SpecialPowers.spawn(browser, [], () => {
content.document.getElementById("one").removeAttribute("aria-current");
});
Expand Down
23 changes: 2 additions & 21 deletions accessible/tests/browser/mac/browser_aria_expanded.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,6 @@

"use strict";

/* import-globals-from ../../mochitest/states.js */
loadScripts({ name: "states.js", dir: MOCHITESTS_DIR });

function waitForStateChange(id, state, isEnabled) {
return waitForEvent(EVENT_STATE_CHANGE, e => {
e.QueryInterface(nsIAccessibleStateChangeEvent);
return (
e.state == state &&
!e.isExtraState &&
isEnabled == e.isEnabled &&
id == getAccessibleDOMNodeID(e.accessible)
);
});
}


// Test aria-expanded on a button
addAccessibleTask(
`hello world<br>
Expand All @@ -29,10 +13,7 @@ addAccessibleTask(
let button = getNativeInterface(accDoc, "b");
is(button.getAttributeValue("AXExpanded"), 0, "button is not expanded");

let stateChanged = Promise.all([
waitForStateChange("b", STATE_EXPANDED, true),
waitForStateChange("b", STATE_COLLAPSED, false),
]);
let stateChanged = waitForEvent(EVENT_STATE_CHANGE, "b");
await SpecialPowers.spawn(browser, [], () => {
content.document
.getElementById("b")
Expand All @@ -41,7 +22,7 @@ addAccessibleTask(
await stateChanged;
is(button.getAttributeValue("AXExpanded"), 1, "button is expanded");

stateChanged = waitForStateChange("b", STATE_EXPANDED, false);
stateChanged = waitForEvent(EVENT_STATE_CHANGE, "b");
await SpecialPowers.spawn(browser, [], () => {
content.document.getElementById("b").removeAttribute("aria-expanded");
});
Expand Down
Loading

0 comments on commit 41530b2

Please sign in to comment.