diff options
Diffstat (limited to 'content/browser/accessibility/browser_accessibility_manager.cc')
-rw-r--r-- | content/browser/accessibility/browser_accessibility_manager.cc | 120 |
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 |