Skip to content

Commit

Permalink
ax_ui: JAWS and NVDA reads the characters as BLANK when traverse thro…
Browse files Browse the repository at this point in the history
…ugh the characters using arrow keys

This is a partial revert of crrev.com/c/3876499 with a difference of
a new AXDummyTreeManager which is a blunt copy of TestAXTreeManager
used as a hot fix. Later, TestAXTreeManager can be inherited from
AXDummyTreeManager and even probably merged with AXTreeManagerBase
or AXPlatformTreeManager.

(cherry picked from commit 88f3833)

Change-Id: I65e04a3875b1bdab53f839933e42d6423d292ab6
Bug: 1366311
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3910168
Reviewed-by: Nektarios Paisios <nektar@chromium.org>
Commit-Queue: Nektarios Paisios <nektar@chromium.org>
Cr-Original-Commit-Position: refs/heads/main@{#1051816}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3922654
Reviewed-by: Srinivas Sista <srinivassista@chromium.org>
Owners-Override: Srinivas Sista <srinivassista@chromium.org>
Commit-Queue: Prudhvikumar Bommana <pbommana@google.com>
Cr-Commit-Position: refs/branch-heads/5326@{#2}
Cr-Branched-From: 1f40050-refs/heads/main@{#1051738}
  • Loading branch information
asurkov authored and Chromium LUCI CQ committed Sep 27, 2022
1 parent 91929ce commit 45075d8
Show file tree
Hide file tree
Showing 6 changed files with 160 additions and 7 deletions.
2 changes: 2 additions & 0 deletions ui/accessibility/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,8 @@ component("accessibility") {
"ax_computed_node_data.cc",
"ax_computed_node_data.h",
"ax_coordinate_system.h",
"ax_dummy_tree_manager.cc",
"ax_dummy_tree_manager.h",
"ax_event_generator.cc",
"ax_event_generator.h",
"ax_export.h",
Expand Down
89 changes: 89 additions & 0 deletions ui/accessibility/ax_dummy_tree_manager.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ui/accessibility/ax_dummy_tree_manager.h"

#include "ui/accessibility/ax_node.h"
#include "ui/accessibility/ax_tree_data.h"
#include "ui/accessibility/ax_tree_manager_map.h"

namespace ui {

AXDummyTreeManager::AXDummyTreeManager() = default;

AXDummyTreeManager::AXDummyTreeManager(std::unique_ptr<AXTree> tree)
: AXTreeManager(std::move(tree)) {}

AXDummyTreeManager::AXDummyTreeManager(AXDummyTreeManager&& manager)
: AXTreeManager(std::move(manager.ax_tree_)) {
if (ax_tree_) {
GetMap().RemoveTreeManager(GetTreeID());
GetMap().AddTreeManager(GetTreeID(), this);
}
}

AXDummyTreeManager& AXDummyTreeManager::operator=(
AXDummyTreeManager&& manager) {
if (this == &manager)
return *this;
if (manager.ax_tree_)
GetMap().RemoveTreeManager(manager.GetTreeID());
// std::move(nullptr) == nullptr, so no need to check if `manager.tree_` is
// assigned.
SetTree(std::move(manager.ax_tree_));
return *this;
}

AXDummyTreeManager::~AXDummyTreeManager() = default;

void AXDummyTreeManager::DestroyTree() {
if (!ax_tree_)
return;

GetMap().RemoveTreeManager(GetTreeID());
ax_tree_.reset();
}

AXTree* AXDummyTreeManager::GetTree() const {
DCHECK(ax_tree_) << "Did you forget to call SetTree?";
return ax_tree_.get();
}

void AXDummyTreeManager::SetTree(std::unique_ptr<AXTree> tree) {
if (ax_tree_)
GetMap().RemoveTreeManager(GetTreeID());

ax_tree_ = std::move(tree);
ax_tree_id_ = GetTreeID();
if (ax_tree_)
GetMap().AddTreeManager(GetTreeID(), this);
}

AXNode* AXDummyTreeManager::GetNodeFromTree(const AXTreeID& tree_id,
const AXNodeID node_id) const {
return (ax_tree_ && GetTreeID() == tree_id) ? ax_tree_->GetFromId(node_id)
: nullptr;
}

AXNode* AXDummyTreeManager::GetParentNodeFromParentTreeAsAXNode() const {
AXTreeID parent_tree_id = GetParentTreeID();
AXDummyTreeManager* parent_manager =
static_cast<AXDummyTreeManager*>(AXTreeManager::FromID(parent_tree_id));
if (!parent_manager)
return nullptr;

std::set<AXNodeID> host_node_ids =
parent_manager->GetTree()->GetNodeIdsForChildTreeId(GetTreeID());

for (AXNodeID host_node_id : host_node_ids) {
AXNode* parent_node =
parent_manager->GetNodeFromTree(parent_tree_id, host_node_id);
if (parent_node)
return parent_node;
}

return nullptr;
}

} // namespace ui
54 changes: 54 additions & 0 deletions ui/accessibility/ax_dummy_tree_manager.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef UI_ACCESSIBILITY_AX_DUMMY_TREE_MANAGER_H_
#define UI_ACCESSIBILITY_AX_DUMMY_TREE_MANAGER_H_

#include <memory>

#include "ui/accessibility/ax_export.h"
#include "ui/accessibility/ax_tree.h"
#include "ui/accessibility/ax_tree_id.h"
#include "ui/accessibility/ax_tree_manager.h"

namespace ui {

class AXNode;

// A basic implementation of AXTreeManager.
//
// For simplicity, this class supports only a single tree and doesn't perform
// any walking across multiple trees.
class AX_EXPORT AXDummyTreeManager : public AXTreeManager {
public:
// This constructor does not create an empty AXTree. Call "SetTree" if you
// need to manage a specific tree. Useful when you need to test for the
// situation when no AXTree has been loaded yet.
AXDummyTreeManager();

// Takes ownership of |tree|.
explicit AXDummyTreeManager(std::unique_ptr<AXTree> tree);

~AXDummyTreeManager() override;

AXDummyTreeManager(const AXDummyTreeManager& manager) = delete;
AXDummyTreeManager& operator=(const AXDummyTreeManager& manager) = delete;

AXDummyTreeManager(AXDummyTreeManager&& manager);
AXDummyTreeManager& operator=(AXDummyTreeManager&& manager);

void DestroyTree();
AXTree* GetTree() const;
// Takes ownership of |tree|.
void SetTree(std::unique_ptr<AXTree> tree);

// AXTreeManager implementation.
AXNode* GetNodeFromTree(const AXTreeID& tree_id,
const AXNodeID node_id) const override;
AXNode* GetParentNodeFromParentTreeAsAXNode() const override;
};

} // namespace ui

#endif // UI_ACCESSIBILITY_AX_DUMMY_TREE_MANAGER_H_
1 change: 1 addition & 0 deletions ui/accessibility/ax_tree_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ class AX_EXPORT AXTreeManager : public AXTreeObserver {
static absl::optional<AXTreeID> last_focused_node_tree_id_;

private:
friend class AXDummyTreeManager;
friend class TestAXTreeManager;

static AXTreeManagerMap& GetMap();
Expand Down
15 changes: 10 additions & 5 deletions ui/views/accessibility/view_ax_platform_node_delegate.cc
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "ui/accessibility/ax_action_data.h"
#include "ui/accessibility/ax_dummy_tree_manager.h"
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/accessibility/ax_role_properties.h"
#include "ui/accessibility/ax_tree.h"
Expand Down Expand Up @@ -446,21 +447,25 @@ ViewAXPlatformNodeDelegate::CreateTextPositionAt(
if (!IsDescendantOfAtomicTextField())
return ui::AXNodePosition::CreateNullPosition();

if (!dummy_tree_) {
if (!dummy_tree_manager_) {
ui::AXTreeUpdate initial_state;
initial_state.root_id = GetData().id;
initial_state.nodes = {GetData()};
initial_state.has_tree_data = true;
initial_state.tree_data.tree_id = ui::AXTreeID::CreateNewAXTreeID();
dummy_tree_ = std::make_unique<ui::AXTree>(initial_state);
auto dummy_tree = std::make_unique<ui::AXTree>(initial_state);
dummy_tree_manager_ =
std::make_unique<ui::AXDummyTreeManager>(std::move(dummy_tree));
} else {
DCHECK(dummy_tree_manager_->ax_tree());
ui::AXTreeUpdate update;
update.nodes = {GetData()};
dummy_tree_->Unserialize(update);
const_cast<ui::AXTree*>(dummy_tree_manager_->ax_tree())
->Unserialize(update);
}

return ui::AXNodePosition::CreatePosition(*dummy_tree_->root(), offset,
affinity);
return ui::AXNodePosition::CreatePosition(*dummy_tree_manager_->GetRoot(),
offset, affinity);
}

gfx::NativeViewAccessible ViewAXPlatformNodeDelegate::GetNSWindow() {
Expand Down
6 changes: 4 additions & 2 deletions ui/views/accessibility/view_ax_platform_node_delegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ namespace ui {

struct AXActionData;
class AXUniqueId;
class AXDummyTreeManager;

} // namespace ui

Expand Down Expand Up @@ -155,8 +156,9 @@ class ViewAXPlatformNodeDelegate : public ViewAccessibility,
// Gets the real (non-virtual) TableView, otherwise nullptr.
TableView* GetAncestorTableView() const;

// A tree that is used to hook up `AXPosition` to text fields in Views.
mutable std::unique_ptr<ui::AXTree> dummy_tree_;
// A tree manager that is used to hook up `AXPosition` to text fields in
// Views.
mutable std::unique_ptr<ui::AXDummyTreeManager> dummy_tree_manager_;

// We own this, but it is reference-counted on some platforms so we can't use
// a unique_ptr. It is destroyed in the destructor.
Expand Down

0 comments on commit 45075d8

Please sign in to comment.