1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/extensions/api/automation_internal/automation_util.h"
10 #include "base/values.h"
11 #include "chrome/browser/accessibility/ax_tree_id_registry.h"
12 #include "chrome/common/extensions/api/automation_internal.h"
13 #include "extensions/browser/event_router.h"
14 #include "ui/accessibility/ax_enums.h"
15 #include "ui/accessibility/ax_node_data.h"
17 namespace extensions
{
21 void PopulateNodeData(const ui::AXNodeData
& node_data
,
22 linked_ptr
< api::automation_internal::AXNodeData
>& out_node_data
) {
23 out_node_data
->id
= node_data
.id
;
24 out_node_data
->role
= ToString(node_data
.role
);
26 uint32 state_pos
= 0, state_shifter
= node_data
.state
;
27 while (state_shifter
) {
28 if (state_shifter
& 1) {
29 out_node_data
->state
.additional_properties
.SetBoolean(
30 ToString(static_cast<ui::AXState
>(state_pos
)), true);
32 state_shifter
= state_shifter
>> 1;
36 out_node_data
->location
.left
= node_data
.location
.x();
37 out_node_data
->location
.top
= node_data
.location
.y();
38 out_node_data
->location
.width
= node_data
.location
.width();
39 out_node_data
->location
.height
= node_data
.location
.height();
41 if (!node_data
.bool_attributes
.empty()) {
42 out_node_data
->bool_attributes
.reset(
43 new api::automation_internal::AXNodeData::BoolAttributes());
44 for (size_t i
= 0; i
< node_data
.bool_attributes
.size(); ++i
) {
45 std::pair
<ui::AXBoolAttribute
, bool> attr
=
46 node_data
.bool_attributes
[i
];
47 out_node_data
->bool_attributes
->additional_properties
.SetBoolean(
48 ToString(attr
.first
), attr
.second
);
52 if (!node_data
.float_attributes
.empty()) {
53 out_node_data
->float_attributes
.reset(
54 new api::automation_internal::AXNodeData::FloatAttributes());
55 for (size_t i
= 0; i
< node_data
.float_attributes
.size(); ++i
) {
56 std::pair
<ui::AXFloatAttribute
, float> attr
=
57 node_data
.float_attributes
[i
];
58 out_node_data
->float_attributes
->additional_properties
.SetDouble(
59 ToString(attr
.first
), attr
.second
);
63 if (!node_data
.html_attributes
.empty()) {
64 out_node_data
->html_attributes
.reset(
65 new api::automation_internal::AXNodeData::HtmlAttributes());
66 for (size_t i
= 0; i
< node_data
.html_attributes
.size(); ++i
) {
67 std::pair
<std::string
, std::string
> attr
= node_data
.html_attributes
[i
];
68 out_node_data
->html_attributes
->additional_properties
.SetString(
69 attr
.first
, attr
.second
);
73 if (!node_data
.int_attributes
.empty()) {
74 out_node_data
->int_attributes
.reset(
75 new api::automation_internal::AXNodeData::IntAttributes());
76 for (size_t i
= 0; i
< node_data
.int_attributes
.size(); ++i
) {
77 std::pair
<ui::AXIntAttribute
, int> attr
= node_data
.int_attributes
[i
];
78 out_node_data
->int_attributes
->additional_properties
.SetInteger(
79 ToString(attr
.first
), attr
.second
);
83 if (!node_data
.intlist_attributes
.empty()) {
84 out_node_data
->intlist_attributes
.reset(
85 new api::automation_internal::AXNodeData::IntlistAttributes());
86 for (size_t i
= 0; i
< node_data
.intlist_attributes
.size(); ++i
) {
87 std::pair
<ui::AXIntListAttribute
, std::vector
<int32
> > attr
=
88 node_data
.intlist_attributes
[i
];
89 base::ListValue
* intlist
= new base::ListValue();
90 for (size_t j
= 0; j
< attr
.second
.size(); ++j
)
91 intlist
->AppendInteger(attr
.second
[j
]);
92 out_node_data
->intlist_attributes
->additional_properties
.Set(
93 ToString(attr
.first
), intlist
);
97 if (!node_data
.string_attributes
.empty()) {
98 out_node_data
->string_attributes
.reset(
99 new api::automation_internal::AXNodeData::StringAttributes());
100 for (size_t i
= 0; i
< node_data
.string_attributes
.size(); ++i
) {
101 std::pair
<ui::AXStringAttribute
, std::string
> attr
=
102 node_data
.string_attributes
[i
];
103 out_node_data
->string_attributes
->additional_properties
.SetString(
104 ToString(attr
.first
), attr
.second
);
108 for (size_t i
= 0; i
< node_data
.child_ids
.size(); ++i
) {
109 out_node_data
->child_ids
.push_back(node_data
.child_ids
[i
]);
113 void DispatchEventInternal(content::BrowserContext
* context
,
114 const std::string
& event_name
,
115 scoped_ptr
<base::ListValue
> args
) {
116 if (context
&& EventRouter::Get(context
)) {
117 scoped_ptr
<Event
> event(new Event(event_name
, args
.Pass()));
118 event
->restrict_to_browser_context
= context
;
119 EventRouter::Get(context
)->BroadcastEvent(event
.Pass());
125 namespace automation_util
{
127 void DispatchAccessibilityEventsToAutomation(
128 const std::vector
<content::AXEventNotificationDetails
>& details
,
129 content::BrowserContext
* browser_context
,
130 const gfx::Vector2d
& location_offset
) {
131 using api::automation_internal::AXEventParams
;
132 using api::automation_internal::AXTreeUpdate
;
134 std::vector
<content::AXEventNotificationDetails
>::const_iterator iter
=
136 for (; iter
!= details
.end(); ++iter
) {
137 const content::AXEventNotificationDetails
& event
= *iter
;
139 AXEventParams ax_event_params
;
140 ax_event_params
.tree_id
=
141 AXTreeIDRegistry::GetInstance()->GetOrCreateAXTreeID(event
.process_id
,
143 ax_event_params
.event_type
= ToString(iter
->event_type
);
144 ax_event_params
.target_id
= event
.id
;
146 AXTreeUpdate
& ax_tree_update
= ax_event_params
.update
;
147 ax_tree_update
.node_id_to_clear
= event
.node_id_to_clear
;
148 for (size_t i
= 0; i
< event
.nodes
.size(); ++i
) {
149 ui::AXNodeData src
= event
.nodes
[i
];
150 src
.location
.Offset(location_offset
);
151 linked_ptr
<api::automation_internal::AXNodeData
> out_node(
152 new api::automation_internal::AXNodeData());
153 PopulateNodeData(src
, out_node
);
154 ax_tree_update
.nodes
.push_back(out_node
);
157 // TODO(dtseng/aboxhall): Why are we sending only one update at a time? We
158 // should match the behavior from renderer -> browser and send a
159 // collection of tree updates over (to the extension); see
160 // |AccessibilityHostMsg_EventParams| and |AccessibilityHostMsg_Events|.
161 DispatchEventInternal(
163 api::automation_internal::OnAccessibilityEvent::kEventName
,
164 api::automation_internal::OnAccessibilityEvent::Create(
169 void DispatchTreeDestroyedEventToAutomation(
172 content::BrowserContext
* browser_context
) {
173 int tree_id
= AXTreeIDRegistry::GetInstance()->GetOrCreateAXTreeID(
174 process_id
, routing_id
);
175 DispatchEventInternal(
177 api::automation_internal::OnAccessibilityTreeDestroyed::kEventName
,
178 api::automation_internal::OnAccessibilityTreeDestroyed::Create(tree_id
));
179 AXTreeIDRegistry::GetInstance()->RemoveAXTreeID(tree_id
);
182 } // namespace automation_util
184 } // namespace extensions