This source file includes following definitions.
- Create
 
- Create
 
- osk_state_
 
- osk_state_
 
- Initialize
 
- GetEmptyDocument
 
- GetRoot
 
- GetFromRendererID
 
- OnWindowFocused
 
- OnWindowBlurred
 
- GotMouseDown
 
- IsOSKAllowed
 
- UseRootScrollOffsetsWhenComputingBounds
 
- RemoveNode
 
- OnAccessibilityEvents
 
- OnLocationChanges
 
- GetFocus
 
- SetFocus
 
- SetRoot
 
- DoDefaultAction
 
- ScrollToMakeVisible
 
- ScrollToPoint
 
- SetTextSelection
 
- GetViewBounds
 
- NextInTreeOrder
 
- PreviousInTreeOrder
 
- UpdateNodesForTesting
 
- UpdateNodes
 
- CreateNode
 
- AddNodeToMap
 
- UpdateNode
 
#include "content/browser/accessibility/browser_accessibility_manager.h"
#include "base/logging.h"
#include "content/browser/accessibility/browser_accessibility.h"
#include "content/common/accessibility_messages.h"
namespace content {
BrowserAccessibility* BrowserAccessibilityFactory::Create() {
  return BrowserAccessibility::Create();
}
#if !defined(OS_MACOSX) && \
    !defined(OS_WIN) && \
    !defined(TOOLKIT_GTK) && \
    !defined(OS_ANDROID) \
BrowserAccessibilityManager* BrowserAccessibilityManager::Create(
    const ui::AXNodeData& src,
    BrowserAccessibilityDelegate* delegate,
    BrowserAccessibilityFactory* factory) {
  return new BrowserAccessibilityManager(src, delegate, factory);
}
#endif
BrowserAccessibilityManager::BrowserAccessibilityManager(
    BrowserAccessibilityDelegate* delegate,
    BrowserAccessibilityFactory* factory)
    : delegate_(delegate),
      factory_(factory),
      root_(NULL),
      focus_(NULL),
      osk_state_(OSK_ALLOWED) {
}
BrowserAccessibilityManager::BrowserAccessibilityManager(
    const ui::AXNodeData& src,
    BrowserAccessibilityDelegate* delegate,
    BrowserAccessibilityFactory* factory)
    : delegate_(delegate),
      factory_(factory),
      root_(NULL),
      focus_(NULL),
      osk_state_(OSK_ALLOWED) {
  Initialize(src);
}
BrowserAccessibilityManager::~BrowserAccessibilityManager() {
  if (root_)
    root_->Destroy();
}
void BrowserAccessibilityManager::Initialize(const ui::AXNodeData src) {
  std::vector<ui::AXNodeData> nodes;
  nodes.push_back(src);
  if (!UpdateNodes(nodes))
    return;
  if (!focus_)
    SetFocus(root_, false);
}
ui::AXNodeData BrowserAccessibilityManager::GetEmptyDocument() {
  ui::AXNodeData empty_document;
  empty_document.id = 0;
  empty_document.role = ui::AX_ROLE_ROOT_WEB_AREA;
  return empty_document;
}
BrowserAccessibility* BrowserAccessibilityManager::GetRoot() {
  return root_;
}
BrowserAccessibility* BrowserAccessibilityManager::GetFromRendererID(
    int32 renderer_id) {
  base::hash_map<int32, BrowserAccessibility*>::iterator iter =
      renderer_id_map_.find(renderer_id);
  if (iter != renderer_id_map_.end())
    return iter->second;
  return NULL;
}
void BrowserAccessibilityManager::OnWindowFocused() {
  if (focus_)
    NotifyAccessibilityEvent(ui::AX_EVENT_FOCUS, focus_);
}
void BrowserAccessibilityManager::OnWindowBlurred() {
  if (focus_)
    NotifyAccessibilityEvent(ui::AX_EVENT_BLUR, focus_);
}
void BrowserAccessibilityManager::GotMouseDown() {
  osk_state_ = OSK_ALLOWED_WITHIN_FOCUSED_OBJECT;
  NotifyAccessibilityEvent(ui::AX_EVENT_FOCUS, focus_);
}
bool BrowserAccessibilityManager::IsOSKAllowed(const gfx::Rect& bounds) {
  if (!delegate_ || !delegate_->HasFocus())
    return false;
  gfx::Point touch_point = delegate_->GetLastTouchEventLocation();
  return bounds.Contains(touch_point);
}
bool BrowserAccessibilityManager::UseRootScrollOffsetsWhenComputingBounds() {
  return true;
}
void BrowserAccessibilityManager::RemoveNode(BrowserAccessibility* node) {
  if (node == focus_)
    SetFocus(root_, false);
  int renderer_id = node->renderer_id();
  renderer_id_map_.erase(renderer_id);
}
void BrowserAccessibilityManager::OnAccessibilityEvents(
    const std::vector<AccessibilityHostMsg_EventParams>& params) {
  bool should_send_initial_focus = false;
  
  for (uint32 index = 0; index < params.size(); index++) {
    const AccessibilityHostMsg_EventParams& param = params[index];
    if (!UpdateNodes(param.update.nodes))
      return;
    
    ui::AXEvent event_type = param.event_type;
    if (event_type == ui::AX_EVENT_LOAD_COMPLETE) {
      if (!focus_) {
        SetFocus(root_, false);
        should_send_initial_focus = true;
      }
    }
  }
  if (should_send_initial_focus &&
      (!delegate_ || delegate_->HasFocus())) {
    NotifyAccessibilityEvent(ui::AX_EVENT_FOCUS, focus_);
  }
  
  for (uint32 index = 0; index < params.size(); index++) {
    const AccessibilityHostMsg_EventParams& param = params[index];
    
    
    BrowserAccessibility* node = GetFromRendererID(param.id);
    if (!node)
      continue;
    ui::AXEvent event_type = param.event_type;
    if (event_type == ui::AX_EVENT_FOCUS ||
        event_type == ui::AX_EVENT_BLUR) {
      SetFocus(node, false);
      if (osk_state_ != OSK_DISALLOWED_BECAUSE_TAB_HIDDEN &&
          osk_state_ != OSK_DISALLOWED_BECAUSE_TAB_JUST_APPEARED)
        osk_state_ = OSK_ALLOWED;
      
      
      if (delegate_ && !delegate_->HasFocus())
        continue;
    }
    
    NotifyAccessibilityEvent(event_type, node);
  }
}
void BrowserAccessibilityManager::OnLocationChanges(
    const std::vector<AccessibilityHostMsg_LocationChangeParams>& params) {
  for (size_t i = 0; i < params.size(); ++i) {
    BrowserAccessibility* node = GetFromRendererID(params[i].id);
    if (node)
      node->SetLocation(params[i].new_location);
  }
}
BrowserAccessibility* BrowserAccessibilityManager::GetFocus(
    BrowserAccessibility* root) {
  if (focus_ && (!root || focus_->IsDescendantOf(root)))
    return focus_;
  return NULL;
}
void BrowserAccessibilityManager::SetFocus(
    BrowserAccessibility* node, bool notify) {
  if (focus_ != node)
    focus_ = node;
  if (notify && node && delegate_)
    delegate_->SetAccessibilityFocus(node->renderer_id());
}
void BrowserAccessibilityManager::SetRoot(BrowserAccessibility* node) {
  root_ = node;
  NotifyRootChanged();
}
void BrowserAccessibilityManager::DoDefaultAction(
    const BrowserAccessibility& node) {
  if (delegate_)
    delegate_->AccessibilityDoDefaultAction(node.renderer_id());
}
void BrowserAccessibilityManager::ScrollToMakeVisible(
    const BrowserAccessibility& node, gfx::Rect subfocus) {
  if (delegate_) {
    delegate_->AccessibilityScrollToMakeVisible(node.renderer_id(), subfocus);
  }
}
void BrowserAccessibilityManager::ScrollToPoint(
    const BrowserAccessibility& node, gfx::Point point) {
  if (delegate_) {
    delegate_->AccessibilityScrollToPoint(node.renderer_id(), point);
  }
}
void BrowserAccessibilityManager::SetTextSelection(
    const BrowserAccessibility& node, int start_offset, int end_offset) {
  if (delegate_) {
    delegate_->AccessibilitySetTextSelection(
        node.renderer_id(), start_offset, end_offset);
  }
}
gfx::Rect BrowserAccessibilityManager::GetViewBounds() {
  if (delegate_)
    return delegate_->GetViewBounds();
  return gfx::Rect();
}
BrowserAccessibility* BrowserAccessibilityManager::NextInTreeOrder(
    BrowserAccessibility* node) {
  if (!node)
    return NULL;
  if (node->PlatformChildCount() > 0)
    return node->PlatformGetChild(0);
  while (node) {
    if (node->parent() &&
        node->index_in_parent() <
            static_cast<int>(node->parent()->PlatformChildCount()) - 1) {
      return node->parent()->PlatformGetChild(node->index_in_parent() + 1);
    }
    node = node->parent();
  }
  return NULL;
}
BrowserAccessibility* BrowserAccessibilityManager::PreviousInTreeOrder(
    BrowserAccessibility* node) {
  if (!node)
    return NULL;
  if (node->parent() && node->index_in_parent() > 0) {
    node = node->parent()->PlatformGetChild(node->index_in_parent() - 1);
    while (node->PlatformChildCount() > 0)
      node = node->PlatformGetChild(node->PlatformChildCount() - 1);
    return node;
  }
  return node->parent();
}
void BrowserAccessibilityManager::UpdateNodesForTesting(
    const ui::AXNodeData& node1,
    const ui::AXNodeData& node2 ,
    const ui::AXNodeData& node3 ,
    const ui::AXNodeData& node4 ,
    const ui::AXNodeData& node5 ,
    const ui::AXNodeData& node6 ,
    const ui::AXNodeData& node7 ) {
  std::vector<ui::AXNodeData> nodes;
  nodes.push_back(node1);
  if (node2.id != ui::AXNodeData().id)
    nodes.push_back(node2);
  if (node3.id != ui::AXNodeData().id)
    nodes.push_back(node3);
  if (node4.id != ui::AXNodeData().id)
    nodes.push_back(node4);
  if (node5.id != ui::AXNodeData().id)
    nodes.push_back(node5);
  if (node6.id != ui::AXNodeData().id)
    nodes.push_back(node6);
  if (node7.id != ui::AXNodeData().id)
    nodes.push_back(node7);
  UpdateNodes(nodes);
}
bool BrowserAccessibilityManager::UpdateNodes(
    const std::vector<ui::AXNodeData>& nodes) {
  bool success = true;
  
  for (size_t i = 0; i < nodes.size() && success; i++) {
    if (!UpdateNode(nodes[i]))
      success = false;
  }
  
  
  for (size_t i = 0; i < nodes.size() && success; i++) {
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    BrowserAccessibility* instance = GetFromRendererID(nodes[i].id);
    if (instance)
      instance->PostInitialize();
  }
  if (!success) {
    
    
    
    if (delegate_)
      delegate_->FatalAccessibilityTreeError();
    else
      CHECK(false);
  }
  return success;
}
BrowserAccessibility* BrowserAccessibilityManager::CreateNode(
    BrowserAccessibility* parent,
    int32 renderer_id,
    int32 index_in_parent) {
  BrowserAccessibility* node = factory_->Create();
  node->InitializeTreeStructure(
      this, parent, renderer_id, index_in_parent);
  AddNodeToMap(node);
  return node;
}
void BrowserAccessibilityManager::AddNodeToMap(BrowserAccessibility* node) {
  renderer_id_map_[node->renderer_id()] = node;
}
bool BrowserAccessibilityManager::UpdateNode(const ui::AXNodeData& src) {
  
  
  
  
  std::set<int32> new_child_ids;
  for (size_t i = 0; i < src.child_ids.size(); ++i) {
    if (new_child_ids.find(src.child_ids[i]) != new_child_ids.end())
      return false;
    new_child_ids.insert(src.child_ids[i]);
  }
  
  
  
  BrowserAccessibility* instance = GetFromRendererID(src.id);
  if (!instance) {
    if (src.role != ui::AX_ROLE_ROOT_WEB_AREA)
      return false;
    instance = CreateNode(NULL, src.id, 0);
  }
  
  instance->InitializeData(src);
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  const std::vector<BrowserAccessibility*>& old_children = instance->children();
  for (size_t i = 0; i < old_children.size(); ++i) {
    int old_id = old_children[i]->renderer_id();
    if (new_child_ids.find(old_id) == new_child_ids.end())
      old_children[i]->Destroy();
  }
  
  
  std::vector<BrowserAccessibility*> new_children;
  bool success = true;
  for (size_t i = 0; i < src.child_ids.size(); i++) {
    int32 child_renderer_id = src.child_ids[i];
    int32 index_in_parent = static_cast<int32>(i);
    BrowserAccessibility* child = GetFromRendererID(child_renderer_id);
    if (child) {
      if (child->parent() != instance) {
        
        
        
        success = false;
        continue;
      }
      child->UpdateParent(instance, index_in_parent);
    } else {
      child = CreateNode(instance, child_renderer_id, index_in_parent);
    }
    new_children.push_back(child);
  }
  
  instance->SwapChildren(new_children);
  
  if (src.role == ui::AX_ROLE_ROOT_WEB_AREA &&
      (!root_ || root_->renderer_id() != src.id)) {
    if (root_)
      root_->Destroy();
    if (focus_ == root_)
      SetFocus(instance, false);
    SetRoot(instance);
  }
  
  if (src.role != ui::AX_ROLE_ROOT_WEB_AREA &&
      src.role != ui::AX_ROLE_WEB_AREA &&
      (src.state >> ui::AX_STATE_FOCUSED & 1)) {
    SetFocus(instance, false);
  }
  return success;
}
}