tor-browser

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

commit 508bd44a39fb44bcad2779cdb9d2c060e083c780
parent bb1d99b2c9e2cb624064dfcaff73d42e2f754022
Author: Eitan Isaacson <eitan@monotonous.org>
Date:   Wed, 22 Oct 2025 03:12:53 +0000

Bug 1942799 - P1: Intro IsEditable(Root) to distinguish editable content. r=morgan

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

Diffstat:
Maccessible/basetypes/Accessible.cpp | 29+++++++++++++++++++++++++++++
Maccessible/basetypes/Accessible.h | 4++++
Maccessible/generic/HyperTextAccessible.cpp | 7-------
Maccessible/generic/HyperTextAccessible.h | 5-----
Maccessible/generic/LocalAccessible.cpp | 5+++++
Maccessible/generic/LocalAccessible.h | 2++
Maccessible/ipc/RemoteAccessible.cpp | 16++++++++++++++++
Maccessible/ipc/RemoteAccessible.h | 2++
Maccessible/xul/XULTreeGridAccessible.cpp | 6+++---
Maccessible/xul/XULTreeGridAccessible.h | 5+++--
10 files changed, 64 insertions(+), 17 deletions(-)

diff --git a/accessible/basetypes/Accessible.cpp b/accessible/basetypes/Accessible.cpp @@ -199,6 +199,35 @@ bool Accessible::IsTextRole() { return true; } +bool Accessible::IsEditableRoot() const { + if (IsTextField()) { + // A text field is always an editable root. + return true; + } + + const nsRoleMapEntry* roleMapEntry = ARIARoleMap(); + if (roleMapEntry && (roleMapEntry->role == roles::ENTRY || + roleMapEntry->role == roles::SEARCHBOX)) { + // An aria text field is always an editable root. + return true; + } + + if (!IsEditable()) { + return false; + } + + if (IsDoc()) { + return true; + } + + Accessible* parent = Parent(); + if (parent && !parent->IsEditable()) { + return true; + } + + return false; +} + uint32_t Accessible::StartOffset() { MOZ_ASSERT(IsLink(), "StartOffset is called not on hyper link!"); Accessible* parent = Parent(); diff --git a/accessible/basetypes/Accessible.h b/accessible/basetypes/Accessible.h @@ -623,6 +623,10 @@ class Accessible { */ bool IsTextRole(); + virtual bool IsEditable() const = 0; + + bool IsEditableRoot() const; + bool IsGenericHyperText() const { return mType == eHyperTextType; } bool IsHTMLBr() const { return mType == eHTMLBRType; } diff --git a/accessible/generic/HyperTextAccessible.cpp b/accessible/generic/HyperTextAccessible.cpp @@ -85,13 +85,6 @@ uint64_t HyperTextAccessible::NativeState() const { return states; } -bool HyperTextAccessible::IsEditable() const { - if (!mContent) { - return false; - } - return mContent->AsElement()->State().HasState(dom::ElementState::READWRITE); -} - uint32_t HyperTextAccessible::DOMPointToOffset(nsINode* aNode, int32_t aNodeOffset, bool aIsEndOffset) const { diff --git a/accessible/generic/HyperTextAccessible.h b/accessible/generic/HyperTextAccessible.h @@ -59,11 +59,6 @@ class HyperTextAccessible : public AccessibleWrap, LocalAccessible* aChild) override; virtual Relation RelationByType(RelationType aType) const override; - /** - * Return whether the associated content is editable. - */ - bool IsEditable() const; - // HyperTextAccessible (static helper method) // Convert content offset to rendered text offset diff --git a/accessible/generic/LocalAccessible.cpp b/accessible/generic/LocalAccessible.cpp @@ -2534,6 +2534,11 @@ bool LocalAccessible::IsPopover() const { return el && el->IsHTMLElement() && el->HasAttr(nsGkAtoms::popover); } +bool LocalAccessible::IsEditable() const { + dom::Element* el = Elm(); + return el && el->State().HasState(dom::ElementState::READWRITE); +} + void LocalAccessible::AppendTextTo(nsAString& aText, uint32_t aStartOffset, uint32_t aLength) { // Return text representation of non-text accessible within hypertext diff --git a/accessible/generic/LocalAccessible.h b/accessible/generic/LocalAccessible.h @@ -429,6 +429,8 @@ class LocalAccessible : public nsISupports, public Accessible { virtual bool IsPopover() const override; + virtual bool IsEditable() const override; + /** * Get a pointer to accessibility interface for this node, which is specific * to the OS/accessibility toolkit we're running on. diff --git a/accessible/ipc/RemoteAccessible.cpp b/accessible/ipc/RemoteAccessible.cpp @@ -1560,6 +1560,22 @@ bool RemoteAccessible::IsPopover() const { return mCachedFields && mCachedFields->HasAttribute(CacheKey::PopupType); } +bool RemoteAccessible::IsEditable() const { + if (RequestDomainsIfInactive(CacheDomain::State)) { + return false; + } + + if (mCachedFields) { + if (auto rawState = + mCachedFields->GetAttribute<uint64_t>(CacheKey::State)) { + VERIFY_CACHE(CacheDomain::State); + return (*rawState & states::EDITABLE) != 0; + } + } + + return false; +} + #if !defined(XP_WIN) void RemoteAccessible::Announce(const nsString& aAnnouncement, uint16_t aPriority) { diff --git a/accessible/ipc/RemoteAccessible.h b/accessible/ipc/RemoteAccessible.h @@ -392,6 +392,8 @@ class RemoteAccessible : public Accessible, public HyperTextAccessibleBase { virtual bool HasPrimaryAction() const override; + virtual bool IsEditable() const override; + #if !defined(XP_WIN) void Announce(const nsString& aAnnouncement, uint16_t aPriority); #endif // !defined(XP_WIN) diff --git a/accessible/xul/XULTreeGridAccessible.cpp b/accessible/xul/XULTreeGridAccessible.cpp @@ -455,7 +455,7 @@ nsRect XULTreeGridCellAccessible::BoundsInAppUnits() const { bool XULTreeGridCellAccessible::HasPrimaryAction() const { return mColumn->Cycler() || (mColumn->Type() == dom::TreeColumn_Binding::TYPE_CHECKBOX && - IsEditable()); + IsEditableCell()); } void XULTreeGridCellAccessible::ActionNameAt(uint8_t aIndex, nsAString& aName) { @@ -469,7 +469,7 @@ void XULTreeGridCellAccessible::ActionNameAt(uint8_t aIndex, nsAString& aName) { } if (mColumn->Type() == dom::TreeColumn_Binding::TYPE_CHECKBOX && - IsEditable()) { + IsEditableCell()) { nsAutoString value; mTreeView->GetCellValue(mRow, mColumn, value); if (value.EqualsLiteral("true")) { @@ -647,7 +647,7 @@ void XULTreeGridCellAccessible::DispatchClickEvent( //////////////////////////////////////////////////////////////////////////////// // XULTreeGridCellAccessible: protected implementation -bool XULTreeGridCellAccessible::IsEditable() const { +bool XULTreeGridCellAccessible::IsEditableCell() const { // XXX: logic corresponds to tree.xml, it's preferable to have interface // method to check it. bool isEditable = false; diff --git a/accessible/xul/XULTreeGridAccessible.h b/accessible/xul/XULTreeGridAccessible.h @@ -171,9 +171,10 @@ class XULTreeGridCellAccessible : public LeafAccessible, // XULTreeGridCellAccessible /** - * Return true if value of cell can be modified. + * Return true if value of cell can be changed. Accounting for the state of + * its column. */ - bool IsEditable() const; + bool IsEditableCell() const; enum { eAction_Click = 0 };