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;
}
}