summaryrefslogtreecommitdiffstats
path: root/content/browser/accessibility/browser_accessibility_manager.cc
diff options
context:
space:
mode:
Diffstat (limited to 'content/browser/accessibility/browser_accessibility_manager.cc')
-rw-r--r--content/browser/accessibility/browser_accessibility_manager.cc120
1 files changed, 100 insertions, 20 deletions
diff --git a/content/browser/accessibility/browser_accessibility_manager.cc b/content/browser/accessibility/browser_accessibility_manager.cc
index f20cce9..4ccca0e 100644
--- a/content/browser/accessibility/browser_accessibility_manager.cc
+++ b/content/browser/accessibility/browser_accessibility_manager.cc
@@ -11,6 +11,35 @@
namespace content {
+namespace {
+
+// Search the tree recursively from |node| and return any node that has
+// a child tree ID of |ax_tree_id|.
+BrowserAccessibility* FindNodeWithChildTreeId(BrowserAccessibility* node,
+ int ax_tree_id) {
+ if (!node)
+ return nullptr;
+
+ if (node->GetIntAttribute(ui::AX_ATTR_CHILD_TREE_ID) == ax_tree_id)
+ return node;
+
+ for (unsigned int i = 0; i < node->InternalChildCount(); ++i) {
+ BrowserAccessibility* child = node->InternalGetChild(i);
+ BrowserAccessibility* result = FindNodeWithChildTreeId(child, ax_tree_id);
+ if (result)
+ return result;
+ }
+
+ return nullptr;
+}
+
+} // namespace
+
+// Map from AXTreeID to BrowserAccessibilityManager
+using AXTreeIDMap =
+ base::hash_map<AXTreeIDRegistry::AXTreeID, BrowserAccessibilityManager*>;
+base::LazyInstance<AXTreeIDMap> g_ax_tree_id_map = LAZY_INSTANCE_INITIALIZER;
+
SimpleAXTreeUpdate MakeAXTreeUpdate(
const ui::AXNodeData& node1,
const ui::AXNodeData& node2 /* = ui::AXNodeData() */,
@@ -73,6 +102,14 @@ BrowserAccessibilityManager* BrowserAccessibilityManager::Create(
}
#endif
+// static
+BrowserAccessibilityManager* BrowserAccessibilityManager::FromID(
+ AXTreeIDRegistry::AXTreeID ax_tree_id) {
+ AXTreeIDMap* ax_tree_id_map = g_ax_tree_id_map.Pointer();
+ auto iter = ax_tree_id_map->find(ax_tree_id);
+ return iter == ax_tree_id_map->end() ? nullptr : iter->second;
+}
+
BrowserAccessibilityManager::BrowserAccessibilityManager(
BrowserAccessibilityDelegate* delegate,
BrowserAccessibilityFactory* factory)
@@ -81,7 +118,9 @@ BrowserAccessibilityManager::BrowserAccessibilityManager(
tree_(new ui::AXSerializableTree()),
focus_(NULL),
user_is_navigating_away_(false),
- osk_state_(OSK_ALLOWED) {
+ osk_state_(OSK_ALLOWED),
+ ax_tree_id_(AXTreeIDRegistry::kNoAXTreeID),
+ parent_node_id_from_parent_tree_(0) {
tree_->SetDelegate(this);
}
@@ -148,6 +187,41 @@ BrowserAccessibility* BrowserAccessibilityManager::GetFromID(int32 id) {
return NULL;
}
+BrowserAccessibility*
+BrowserAccessibilityManager::GetParentNodeFromParentTree() {
+ if (!GetRoot())
+ return nullptr;
+
+ int parent_tree_id = GetRoot()->GetIntAttribute(ui::AX_ATTR_PARENT_TREE_ID);
+ BrowserAccessibilityManager* parent_manager =
+ BrowserAccessibilityManager::FromID(parent_tree_id);
+ if (!parent_manager)
+ return nullptr;
+
+ // Try to use the cached parent node from the most recent time this
+ // was called.
+ if (parent_node_id_from_parent_tree_) {
+ BrowserAccessibility* parent_node = parent_manager->GetFromID(
+ parent_node_id_from_parent_tree_);
+ if (parent_node) {
+ int parent_child_tree_id =
+ parent_node->GetIntAttribute(ui::AX_ATTR_CHILD_TREE_ID);
+ if (parent_child_tree_id == ax_tree_id_)
+ return parent_node;
+ }
+ }
+
+ // If that fails, search for it and cache it for next time.
+ BrowserAccessibility* parent_node = FindNodeWithChildTreeId(
+ parent_manager->GetRoot(), ax_tree_id_);
+ if (parent_node) {
+ parent_node_id_from_parent_tree_ = parent_node->GetId();
+ return parent_node;
+ }
+
+ return nullptr;
+}
+
void BrowserAccessibilityManager::OnWindowFocused() {
if (focus_)
NotifyAccessibilityEvent(ui::AX_EVENT_FOCUS, GetFromAXNode(focus_));
@@ -184,13 +258,13 @@ bool BrowserAccessibilityManager::UseRootScrollOffsetsWhenComputingBounds() {
}
void BrowserAccessibilityManager::OnAccessibilityEvents(
- const std::vector<AccessibilityHostMsg_EventParams>& params) {
+ const std::vector<AXEventNotificationDetails>& details) {
bool should_send_initial_focus = false;
// Process all changes to the accessibility tree first.
- for (uint32 index = 0; index < params.size(); index++) {
- const AccessibilityHostMsg_EventParams& param = params[index];
- if (!tree_->Unserialize(param.update)) {
+ for (uint32 index = 0; index < details.size(); ++index) {
+ const AXEventNotificationDetails& detail = details[index];
+ if (!tree_->Unserialize(detail.update)) {
if (delegate_) {
LOG(ERROR) << tree_->error();
delegate_->AccessibilityFatalError();
@@ -213,16 +287,16 @@ void BrowserAccessibilityManager::OnAccessibilityEvents(
}
// Now iterate over the events again and fire the events.
- for (uint32 index = 0; index < params.size(); index++) {
- const AccessibilityHostMsg_EventParams& param = params[index];
+ for (uint32 index = 0; index < details.size(); index++) {
+ const AXEventNotificationDetails& detail = details[index];
// Find the node corresponding to the id that's the target of the
// event (which may not be the root of the update tree).
- ui::AXNode* node = tree_->GetFromId(param.id);
+ ui::AXNode* node = tree_->GetFromId(detail.id);
if (!node)
continue;
- ui::AXEvent event_type = param.event_type;
+ ui::AXEvent event_type = detail.event_type;
if (event_type == ui::AX_EVENT_FOCUS ||
event_type == ui::AX_EVENT_BLUR) {
SetFocus(node, false);
@@ -317,9 +391,10 @@ BrowserAccessibility* BrowserAccessibilityManager::GetFocus(
return NULL;
BrowserAccessibility* obj = GetFromAXNode(focus_);
- if (delegate() && obj->HasBoolAttribute(ui::AX_ATTR_IS_AX_TREE_HOST)) {
+ if (obj->HasIntAttribute(ui::AX_ATTR_CHILD_TREE_ID)) {
BrowserAccessibilityManager* child_manager =
- delegate()->AccessibilityGetChildFrame(obj->GetId());
+ BrowserAccessibilityManager::FromID(
+ obj->GetIntAttribute(ui::AX_ATTR_CHILD_TREE_ID));
if (child_manager)
return child_manager->GetFocus(child_manager->GetRoot());
}
@@ -464,19 +539,24 @@ void BrowserAccessibilityManager::OnAtomicUpdateFinished(
ui::AXTree* tree,
bool root_changed,
const std::vector<ui::AXTreeDelegate::Change>& changes) {
+ if (GetRoot()->HasIntAttribute(ui::AX_ATTR_TREE_ID) &&
+ GetRoot()->GetIntAttribute(ui::AX_ATTR_TREE_ID) != ax_tree_id_) {
+ g_ax_tree_id_map.Get().erase(ax_tree_id_);
+ ax_tree_id_ = GetRoot()->GetIntAttribute(ui::AX_ATTR_TREE_ID);
+ g_ax_tree_id_map.Get().insert(std::make_pair(ax_tree_id_, this));
+ }
}
BrowserAccessibilityDelegate*
BrowserAccessibilityManager::GetDelegateFromRootManager() {
- BrowserAccessibilityManager* manager = this;
- while (manager->delegate()) {
- BrowserAccessibility* host_node_in_parent_frame =
- manager->delegate()->AccessibilityGetParentFrame();
- if (!host_node_in_parent_frame)
- break;
- manager = host_node_in_parent_frame->manager();
- }
- return manager->delegate();
+ if (!GetRoot())
+ return nullptr;
+ int parent_tree_id = GetRoot()->GetIntAttribute(ui::AX_ATTR_PARENT_TREE_ID);
+ BrowserAccessibilityManager* parent_manager =
+ BrowserAccessibilityManager::FromID(parent_tree_id);
+ if (parent_manager)
+ return parent_manager->GetDelegateFromRootManager();
+ return delegate();
}
SimpleAXTreeUpdate