Bug 1787284: [Part 2] Cache name and create radio name pivot rule r=eeejay

Depends on D158892

Differential Revision: https://phabricator.services.mozilla.com/D159118
This commit is contained in:
Morgan Rae Reschenberg 2022-10-27 20:32:18 +00:00
Родитель 6e6dc5a06e
Коммит dbeec6c2f2
8 изменённых файлов: 94 добавлений и 0 удалений

Просмотреть файл

@ -634,3 +634,29 @@ uint16_t LocalAccInSameDocRule::Match(Accessible* aAcc) {
}
return nsIAccessibleTraversalRule::FILTER_MATCH;
}
// Radio Button Name Rule
PivotRadioNameRule::PivotRadioNameRule(const nsString& aName) : mName(aName) {}
uint16_t PivotRadioNameRule::Match(Accessible* aAcc) {
uint16_t result = nsIAccessibleTraversalRule::FILTER_IGNORE;
RemoteAccessible* remote = aAcc->AsRemote();
if (!remote || !StaticPrefs::accessibility_cache_enabled_AtStartup()) {
// We need the cache to be able to fetch the name attribute below.
return result;
}
if (nsAccUtils::MustPrune(aAcc) || aAcc->IsOuterDoc()) {
result |= nsIAccessibleTraversalRule::FILTER_IGNORE_SUBTREE;
}
if (remote->IsHTMLRadioButton()) {
nsString currName = remote->GetCachedHTMLRadioNameAttribute();
if (!currName.IsEmpty() && mName.Equals(currName)) {
result |= nsIAccessibleTraversalRule::FILTER_MATCH;
}
}
return result;
}

Просмотреть файл

@ -122,6 +122,20 @@ class LocalAccInSameDocRule : public PivotRule {
virtual uint16_t Match(Accessible* aAcc) override;
};
/**
* This rule matches remote radio button accessibles with the given name
* attribute. It assumes the cache is enabled.
*/
class PivotRadioNameRule : public PivotRule {
public:
explicit PivotRadioNameRule(const nsString& aName);
virtual uint16_t Match(Accessible* aAcc) override;
protected:
const nsString& mName;
};
} // namespace a11y
} // namespace mozilla

Просмотреть файл

@ -501,6 +501,8 @@ class Accessible {
bool IsHTMLOptGroup() const { return mType == eHTMLOptGroupType; }
bool IsHTMLRadioButton() const { return mType == eHTMLRadioButtonType; }
bool IsHTMLTable() const { return mType == eHTMLTableType; }
bool IsHTMLTableRow() const { return mType == eHTMLTableRowType; }

Просмотреть файл

@ -3618,6 +3618,21 @@ already_AddRefed<AccAttributes> LocalAccessible::BundleFieldsForCache(
}
if (aCacheDomain & CacheDomain::Relations && mContent) {
if (IsHTMLRadioButton()) {
// HTML radio buttons with the same name should be grouped
// and returned together when their MEMBER_OF relation is
// requested. We cache the name attribute, if it exists, here.
nsString name;
mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::name, name);
if (!name.IsEmpty()) {
fields->SetAttribute(nsGkAtoms::radioLabel, std::move(name));
} else if (aUpdateType != CacheUpdateType::Initial) {
// It's possible we used to have a name and it's since been
// removed. Send a delete entry.
fields->SetAttribute(nsGkAtoms::radioLabel, DeleteEntry());
}
}
for (auto const& data : kRelationTypeAtoms) {
nsTArray<uint64_t> ids;
nsStaticAtom* const relAtom = data.mAtom;

Просмотреть файл

@ -5,6 +5,7 @@
#include "HTMLFormControlAccessible.h"
#include "CacheConstants.h"
#include "DocAccessible-inl.h"
#include "LocalAccessible-inl.h"
#include "nsAccUtils.h"
@ -90,6 +91,20 @@ void HTMLRadioButtonAccessible::GetPositionAndSetSize(int32_t* aPosInSet,
Unused << ComputeGroupAttributes(aPosInSet, aSetSize);
}
void HTMLRadioButtonAccessible::DOMAttributeChanged(
int32_t aNameSpaceID, nsAtom* aAttribute, int32_t aModType,
const nsAttrValue* aOldValue, uint64_t aOldState) {
if (aAttribute == nsGkAtoms::name) {
// If our name changed, it's possible our MEMBER_OF relation
// also changed. Push a cache update for Relations.
mDoc->QueueCacheUpdate(this, CacheDomain::Relations);
} else {
// Otherwise, handle this attribute change the way our parent
// class wants us to handle it.
RadioButtonAccessible::DOMAttributeChanged(aNameSpaceID, aAttribute, aModType, aOldValue, aOldState);
}
}
Relation HTMLRadioButtonAccessible::ComputeGroupAttributes(
int32_t* aPosInSet, int32_t* aSetSize) const {
Relation rel = Relation();

Просмотреть файл

@ -8,6 +8,7 @@
#include "FormControlAccessible.h"
#include "HyperTextAccessibleWrap.h"
#include "mozilla/a11y/AccTypes.h"
#include "mozilla/dom/Element.h"
#include "AccAttributes.h"
#include "nsAccUtils.h"
@ -27,6 +28,7 @@ class HTMLRadioButtonAccessible : public RadioButtonAccessible {
// Ignore "RadioStateChange" DOM event in lieu of document observer
// state change notification.
mStateFlags |= eIgnoreDOMUIEvent;
mType = eHTMLRadioButtonType;
}
// LocalAccessible
@ -37,6 +39,11 @@ class HTMLRadioButtonAccessible : public RadioButtonAccessible {
virtual void GetPositionAndSetSize(int32_t* aPosInSet,
int32_t* aSetSize) override;
virtual void DOMAttributeChanged(int32_t aNameSpaceID, nsAtom* aAttribute,
int32_t aModType,
const nsAttrValue* aOldValue,
uint64_t aOldState) override;
private:
Relation ComputeGroupAttributes(int32_t* aPosInSet, int32_t* aSetSize) const;
};

Просмотреть файл

@ -1006,6 +1006,19 @@ RemoteAccessibleBase<Derived>::GetCachedARIAAttributes() const {
return nullptr;
}
template <class Derived>
nsString RemoteAccessibleBase<Derived>::GetCachedHTMLRadioNameAttribute()
const {
if (mCachedFields) {
if (auto maybeName =
mCachedFields->GetAttribute<nsString>(nsGkAtoms::radioLabel)) {
return *maybeName;
}
}
return nsString();
}
template <class Derived>
uint64_t RemoteAccessibleBase<Derived>::State() {
uint64_t state = 0;

Просмотреть файл

@ -348,6 +348,8 @@ class RemoteAccessibleBase : public Accessible, public HyperTextAccessibleBase {
RefPtr<const AccAttributes> GetCachedTextAttributes();
RefPtr<const AccAttributes> GetCachedARIAAttributes() const;
nsString GetCachedHTMLRadioNameAttribute() const;
virtual HyperTextAccessibleBase* AsHyperTextBase() override {
return IsHyperText() ? static_cast<HyperTextAccessibleBase*>(this)
: nullptr;