tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit 3f346719e60d7ce37c38f0e30e2731a2076e6bde
parent 03e80f7313cfe2bd7fecf8d8777b671bdae35dd5
Author: Eitan Isaacson <eitan@monotonous.org>
Date:   Fri,  3 Oct 2025 14:55:35 +0000

Bug 1990631 - P5: Implement Accessible::Role in Accessible. r=morgan

Use the newly refactored ARIATransformRole to transform a "minimal role"
to a final aria role remotely.

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

Diffstat:
Maccessible/basetypes/Accessible.cpp | 10++++++++++
Maccessible/basetypes/Accessible.h | 7+++++--
Maccessible/generic/LocalAccessible-inl.h | 10----------
Maccessible/generic/LocalAccessible.h | 5-----
Maccessible/ipc/DocAccessibleChild.cpp | 3++-
Maccessible/ipc/DocAccessibleParent.cpp | 2+-
Maccessible/ipc/RemoteAccessible.h | 14+++++++-------
Maccessible/tests/browser/role/browser_roles_generic.js | 34+++++++++++++++++++++++++++++++++-
8 files changed, 58 insertions(+), 27 deletions(-)

diff --git a/accessible/basetypes/Accessible.cpp b/accessible/basetypes/Accessible.cpp @@ -43,6 +43,16 @@ void Accessible::StaticAsserts() const { "Accessible::mGenericType was oversized by eLastAccGenericType!"); } +mozilla::a11y::role Accessible::Role() const { + const nsRoleMapEntry* roleMapEntry = ARIARoleMap(); + mozilla::a11y::role r = + (!roleMapEntry || roleMapEntry->roleRule != kUseMapRole) + ? NativeRole() + : roleMapEntry->role; + r = ARIATransformRole(r); + return GetMinimumRole(r); +} + bool Accessible::IsBefore(const Accessible* aAcc) const { // Build the chain of parents. const Accessible* thisP = this; diff --git a/accessible/basetypes/Accessible.h b/accessible/basetypes/Accessible.h @@ -181,8 +181,6 @@ class Accessible { virtual Accessible* Parent() const = 0; - virtual role Role() const = 0; - virtual role NativeRole() const = 0; /** @@ -197,6 +195,11 @@ class Accessible { virtual int32_t IndexInParent() const = 0; + /** + * Returns the accessible's calculated, final, role. + */ + role Role() const; + bool HasChildren() const { return !!FirstChild(); } inline Accessible* FirstChild() const { diff --git a/accessible/generic/LocalAccessible-inl.h b/accessible/generic/LocalAccessible-inl.h @@ -20,16 +20,6 @@ namespace mozilla { namespace a11y { -inline mozilla::a11y::role LocalAccessible::Role() const { - const nsRoleMapEntry* roleMapEntry = ARIARoleMap(); - mozilla::a11y::role r = - (!roleMapEntry || roleMapEntry->roleRule != kUseMapRole) - ? NativeRole() - : roleMapEntry->role; - r = ARIATransformRole(r); - return GetMinimumRole(r); -} - inline mozilla::a11y::role LocalAccessible::ARIARole() { const nsRoleMapEntry* roleMapEntry = ARIARoleMap(); if (!roleMapEntry || roleMapEntry->roleRule != kUseMapRole) { diff --git a/accessible/generic/LocalAccessible.h b/accessible/generic/LocalAccessible.h @@ -167,11 +167,6 @@ class LocalAccessible : public nsISupports, public Accessible { virtual void ApplyARIAState(uint64_t* aState) const; /** - * Return enumerated accessible role (see constants in Role.h). - */ - virtual mozilla::a11y::role Role() const override; - - /** * Return accessible role specified by ARIA (see constants in * roles). */ diff --git a/accessible/ipc/DocAccessibleChild.cpp b/accessible/ipc/DocAccessibleChild.cpp @@ -76,7 +76,8 @@ AccessibleData DocAccessibleChild::SerializeAcc(LocalAccessible* aAcc) { } } - return AccessibleData(aAcc->ID(), aAcc->Role(), aAcc->LocalParent()->ID(), + return AccessibleData(aAcc->ID(), aAcc->NativeRole(), + aAcc->LocalParent()->ID(), static_cast<int32_t>(aAcc->IndexInParent()), static_cast<AccType>(aAcc->mType), static_cast<AccGenericType>(genericTypes), diff --git a/accessible/ipc/DocAccessibleParent.cpp b/accessible/ipc/DocAccessibleParent.cpp @@ -840,7 +840,7 @@ mozilla::ipc::IPCResult DocAccessibleParent::RecvRoleChangedEvent( return IPC_FAIL(this, "Invalid role map entry index"); } - mRole = aRole; + mNativeRole = aRole; mRoleMapEntryIndex = aRoleMapEntryIndex; #ifdef MOZ_WIDGET_COCOA diff --git a/accessible/ipc/RemoteAccessible.h b/accessible/ipc/RemoteAccessible.h @@ -145,11 +145,11 @@ class RemoteAccessible : public Accessible, public HyperTextAccessibleBase { LocalAccessible* OuterDocOfRemoteBrowser() const; /** - * Get the role of the accessible we're proxying. + * Get the native role of the accessible we're proxying. */ - virtual role Role() const override { return mRole; } - - virtual role NativeRole() const override { return role::NOTHING; } + virtual mozilla::a11y::role NativeRole() const override { + return mNativeRole; + } /** * Return true if this is an embedded object. @@ -436,7 +436,7 @@ class RemoteAccessible : public Accessible, public HyperTextAccessibleBase { mWrapper(0), mID(aID), mCachedFields(nullptr), - mRole(aRole) { + mNativeRole(aRole) { MOZ_COUNT_CTOR(RemoteAccessible); } @@ -446,7 +446,7 @@ class RemoteAccessible : public Accessible, public HyperTextAccessibleBase { mWrapper(0), mID(0), mCachedFields(nullptr), - mRole(roles::DOCUMENT) { + mNativeRole(roles::DOCUMENT) { mGenericTypes = eDocument | eHyperText; MOZ_COUNT_CTOR(RemoteAccessible); } @@ -535,7 +535,7 @@ class RemoteAccessible : public Accessible, public HyperTextAccessibleBase { // XXX DocAccessibleParent gets to change this to change the role of // documents. - role mRole : 27; + role mNativeRole : 27; }; //////////////////////////////////////////////////////////////////////////////// diff --git a/accessible/tests/browser/role/browser_roles_generic.js b/accessible/tests/browser/role/browser_roles_generic.js @@ -338,7 +338,7 @@ addAccessibleTask( <table role="application" id="application_table">application table <tr><td>hi</td></tr></table> <table role="aPPLICATIOn" id="application_table_mixed">application table - <tr><td>hi</td></tr></table> + <tr><td>hi</td></tr></table> <table role="banner" id="banner_table">banner table <tr><td>hi</td></tr></table> <table role="bANNEr" id="banner_table_mixed">banner table @@ -721,3 +721,35 @@ addAccessibleTask( }, { chrome: true, topLevel: true } ); + +/** + * Test re-parented list item's role gets recomputed. + */ +addAccessibleTask( + `<div role="list" id="aria-list"> + </div> + <div role="listitem" id="aria-listitem">Bananas</div>`, + async function testListItemRelocation(browser, accDoc) { + is( + findAccessibleChildByID(accDoc, "aria-listitem").role, + ROLE_SECTION, + "List item in list should have section role" + ); + + let evt = waitForEvent(EVENT_INNER_REORDER, "aria-list"); + await invokeSetAttribute( + browser, + "aria-list", + "aria-owns", + "aria-listitem" + ); + await evt; + + is( + findAccessibleChildByID(accDoc, "aria-listitem").role, + ROLE_LISTITEM, + "List item in list should have listitem role" + ); + }, + { chrome: true, topLevel: true } +);