OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/extensions/api/automation_internal/automation_internal_ api.h" | 5 #include "chrome/browser/extensions/api/automation_internal/automation_internal_ api.h" |
6 | 6 |
7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
8 #include "base/lazy_instance.h" | 8 #include "base/lazy_instance.h" |
9 #include "base/strings/string_number_conversions.h" | 9 #include "base/strings/string_number_conversions.h" |
10 #include "base/values.h" | 10 #include "base/values.h" |
11 #include "chrome/browser/ui/browser.h" | 11 #include "chrome/browser/ui/browser.h" |
12 #include "chrome/browser/ui/tabs/tab_strip_model.h" | 12 #include "chrome/browser/ui/tabs/tab_strip_model.h" |
13 #include "chrome/common/chrome_switches.h" | 13 #include "chrome/common/chrome_switches.h" |
14 #include "chrome/common/extensions/api/automation_internal.h" | 14 #include "chrome/common/extensions/api/automation_internal.h" |
15 #include "content/public/browser/ax_event_notification_details.h" | 15 #include "content/public/browser/ax_event_notification_details.h" |
16 #include "content/public/browser/browser_accessibility_state.h" | 16 #include "content/public/browser/browser_accessibility_state.h" |
17 #include "content/public/browser/browser_thread.h" | 17 #include "content/public/browser/browser_thread.h" |
18 #include "content/public/browser/notification_service.h" | 18 #include "content/public/browser/notification_service.h" |
19 #include "content/public/browser/notification_source.h" | 19 #include "content/public/browser/notification_source.h" |
20 #include "content/public/browser/notification_types.h" | 20 #include "content/public/browser/notification_types.h" |
21 #include "content/public/browser/render_process_host.h" | |
21 #include "content/public/browser/render_view_host.h" | 22 #include "content/public/browser/render_view_host.h" |
22 #include "content/public/browser/render_widget_host.h" | 23 #include "content/public/browser/render_widget_host.h" |
24 #include "content/public/browser/render_widget_host.h" | |
23 #include "content/public/browser/render_widget_host_view.h" | 25 #include "content/public/browser/render_widget_host_view.h" |
24 #include "content/public/browser/web_contents.h" | 26 #include "content/public/browser/web_contents.h" |
25 #include "extensions/browser/event_router.h" | 27 #include "extensions/browser/event_router.h" |
26 #include "extensions/browser/extension_system.h" | 28 #include "extensions/browser/extension_system.h" |
27 #include "ui/accessibility/ax_enums.h" | 29 #include "ui/accessibility/ax_enums.h" |
28 #include "ui/accessibility/ax_node_data.h" | 30 #include "ui/accessibility/ax_node_data.h" |
29 | 31 |
30 namespace extensions { | 32 namespace extensions { |
31 class AutomationWebContentsObserver; | 33 class AutomationWebContentsObserver; |
32 } // namespace extensions | 34 } // namespace extensions |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
66 if (!CommandLine::ForCurrentProcess()->HasSwitch( | 68 if (!CommandLine::ForCurrentProcess()->HasSwitch( |
67 switches::kEnableAutomationAPI)) { | 69 switches::kEnableAutomationAPI)) { |
68 return; | 70 return; |
69 } | 71 } |
70 | 72 |
71 std::vector<content::AXEventNotificationDetails>::const_iterator iter = | 73 std::vector<content::AXEventNotificationDetails>::const_iterator iter = |
72 details.begin(); | 74 details.begin(); |
73 for (; iter != details.end(); iter++) { | 75 for (; iter != details.end(); iter++) { |
74 scoped_ptr<base::ListValue> args(new base::ListValue()); | 76 scoped_ptr<base::ListValue> args(new base::ListValue()); |
75 const content::AXEventNotificationDetails& event = *iter; | 77 const content::AXEventNotificationDetails& event = *iter; |
78 int process_id = event.process_id; | |
76 int routing_id = event.routing_id; | 79 int routing_id = event.routing_id; |
77 | 80 |
78 base::DictionaryValue* axTreeUpdate = new base::DictionaryValue(); | 81 base::DictionaryValue* axTreeUpdate = new base::DictionaryValue(); |
79 // TODO(dtseng): These strings should be auto-generated by the IDL | 82 // TODO(dtseng): These strings should be auto-generated by the IDL |
80 // compiler. | 83 // compiler. |
81 axTreeUpdate->Set("routing_id", | 84 axTreeUpdate->Set("processID", |
85 base::Value::CreateIntegerValue(process_id)); | |
86 axTreeUpdate->Set("routingID", | |
82 base::Value::CreateIntegerValue(routing_id)); | 87 base::Value::CreateIntegerValue(routing_id)); |
83 axTreeUpdate->SetString("event_type", ToString(iter->event_type)); | 88 axTreeUpdate->SetString("eventType", ToString(iter->event_type)); |
not at google - send to devlin
2014/04/03 18:57:13
you should be able to construct these arguments wi
aboxhall
2014/04/03 19:06:31
This seems outside of scope for this change.
not at google - send to devlin
2014/04/03 19:08:02
fair enough.
David Tseng
2014/04/03 23:05:19
I have this pretty much ready for am putting it of
not at google - send to devlin
2014/04/04 16:30:57
You're saying that with the current code you go
a
David Tseng
2014/04/04 17:02:26
Correct.
Yes I think that's true, and if
| |
84 base::ListValue* nodes = new base::ListValue(); | 89 base::ListValue* nodes = new base::ListValue(); |
85 axTreeUpdate->Set("nodes", nodes); | 90 axTreeUpdate->Set("nodes", nodes); |
86 for (size_t i = 0; i < event.nodes.size(); i++) { | 91 for (size_t i = 0; i < event.nodes.size(); i++) { |
87 const ui::AXNodeData& node = event.nodes[i]; | 92 const ui::AXNodeData& node = event.nodes[i]; |
88 AddNodeData(node, nodes); | 93 AddNodeData(node, nodes); |
89 } | 94 } |
90 args->Append(axTreeUpdate); | 95 args->Append(axTreeUpdate); |
91 DispatchEvent(browser_context_, | 96 DispatchEvent(browser_context_, |
92 api::automation_internal::OnAccessibilityEvent::kEventName, | 97 api::automation_internal::OnAccessibilityEvent::kEventName, |
93 args.Pass()); | 98 args.Pass()); |
94 } | 99 } |
95 return; | 100 return; |
96 } | 101 } |
97 | 102 |
98 private: | 103 private: |
99 friend class content::WebContentsUserData<AutomationWebContentsObserver>; | 104 friend class content::WebContentsUserData<AutomationWebContentsObserver>; |
100 | 105 |
101 AutomationWebContentsObserver( | 106 AutomationWebContentsObserver( |
102 content::WebContents* web_contents) | 107 content::WebContents* web_contents) |
103 : content::WebContentsObserver(web_contents), | 108 : content::WebContentsObserver(web_contents), |
104 browser_context_(web_contents->GetBrowserContext()) {} | 109 browser_context_(web_contents->GetBrowserContext()) {} |
105 | 110 |
106 void AddNodeData(const ui::AXNodeData& node, | 111 void AddNodeData(const ui::AXNodeData& node, |
not at google - send to devlin
2014/04/03 18:57:13
you should be able to return, say, a scoped_ptr<AX
| |
107 base::ListValue* nodes) { | 112 base::ListValue* nodes) { |
108 base::DictionaryValue* axNodeData = new base::DictionaryValue(); | 113 base::DictionaryValue* axNodeData = new base::DictionaryValue(); |
109 axNodeData->SetInteger("id", node.id); | 114 axNodeData->SetInteger("id", node.id); |
110 axNodeData->SetString("role", ToString(node.role)); | 115 axNodeData->SetString("role", ToString(node.role)); |
111 | 116 |
112 base::DictionaryValue* state_dict = new base::DictionaryValue(); | 117 base::DictionaryValue* state_dict = new base::DictionaryValue(); |
113 uint32 state_pos = 0, state_shifter = node.state; | 118 uint32 state_pos = 0, state_shifter = node.state; |
114 while (state_shifter) { | 119 while (state_shifter) { |
115 if (state_shifter & 1) | 120 if (state_shifter & 1) |
116 state_dict->SetBoolean(ToString(static_cast<ui::AXState>(state_pos)), | 121 state_dict->SetBoolean(ToString(static_cast<ui::AXState>(state_pos)), |
117 true); | 122 true); |
118 state_shifter = state_shifter >> 1; | 123 state_shifter = state_shifter >> 1; |
119 state_pos++; | 124 state_pos++; |
120 } | 125 } |
121 axNodeData->Set("state", state_dict); | 126 axNodeData->Set("state", state_dict); |
122 | 127 |
123 if (!node.bool_attributes.empty()) { | 128 if (!node.bool_attributes.empty()) { |
124 base::DictionaryValue* bool_attributes = new base::DictionaryValue(); | 129 base::DictionaryValue* bool_attributes = new base::DictionaryValue(); |
125 for (size_t i = 0; i < node.bool_attributes.size(); ++i) { | 130 for (size_t i = 0; i < node.bool_attributes.size(); ++i) { |
126 std::pair<ui::AXBoolAttribute, bool> attr = node.bool_attributes[i]; | 131 std::pair<ui::AXBoolAttribute, bool> attr = node.bool_attributes[i]; |
127 bool_attributes->SetBoolean(ToString(attr.first), attr.second); | 132 bool_attributes->SetBoolean(ToString(attr.first), attr.second); |
128 } | 133 } |
129 axNodeData->Set("bool_attributes", bool_attributes); | 134 axNodeData->Set("boolAttributes", bool_attributes); |
130 } | 135 } |
131 | 136 |
132 if (!node.float_attributes.empty()) { | 137 if (!node.float_attributes.empty()) { |
133 base::DictionaryValue* float_attributes = new base::DictionaryValue(); | 138 base::DictionaryValue* float_attributes = new base::DictionaryValue(); |
134 for (size_t i = 0; i < node.float_attributes.size(); ++i) { | 139 for (size_t i = 0; i < node.float_attributes.size(); ++i) { |
135 std::pair<ui::AXFloatAttribute, float> attr = node.float_attributes[i]; | 140 std::pair<ui::AXFloatAttribute, float> attr = node.float_attributes[i]; |
136 float_attributes->SetDouble(ToString(attr.first), attr.second); | 141 float_attributes->SetDouble(ToString(attr.first), attr.second); |
137 } | 142 } |
138 axNodeData->Set("float_attributes", float_attributes); | 143 axNodeData->Set("floatAttributes", float_attributes); |
139 } | 144 } |
140 | 145 |
141 if (!node.html_attributes.empty()) { | 146 if (!node.html_attributes.empty()) { |
142 base::DictionaryValue* html_attributes = new base::DictionaryValue(); | 147 base::DictionaryValue* html_attributes = new base::DictionaryValue(); |
143 for (size_t i = 0; i < node.html_attributes.size(); ++i) { | 148 for (size_t i = 0; i < node.html_attributes.size(); ++i) { |
144 std::pair<std::string, std::string> attr = node.html_attributes[i]; | 149 std::pair<std::string, std::string> attr = node.html_attributes[i]; |
145 html_attributes->SetString(attr.first, attr.second); | 150 html_attributes->SetString(attr.first, attr.second); |
146 } | 151 } |
147 axNodeData->Set("html_attributes", html_attributes); | 152 axNodeData->Set("htmlAttributes", html_attributes); |
148 } | 153 } |
149 | 154 |
150 if (!node.int_attributes.empty()) { | 155 if (!node.int_attributes.empty()) { |
151 base::DictionaryValue* int_attributes = new base::DictionaryValue(); | 156 base::DictionaryValue* int_attributes = new base::DictionaryValue(); |
152 for (size_t i = 0; i < node.int_attributes.size(); ++i) { | 157 for (size_t i = 0; i < node.int_attributes.size(); ++i) { |
153 std::pair<ui::AXIntAttribute, int> attr = node.int_attributes[i]; | 158 std::pair<ui::AXIntAttribute, int> attr = node.int_attributes[i]; |
154 int_attributes->SetInteger(ToString(attr.first), attr.second); | 159 int_attributes->SetInteger(ToString(attr.first), attr.second); |
155 } | 160 } |
156 axNodeData->Set("int_attributes", int_attributes); | 161 axNodeData->Set("intAttributes", int_attributes); |
157 } | 162 } |
158 | 163 |
159 if (!node.intlist_attributes.empty()) { | 164 if (!node.intlist_attributes.empty()) { |
160 base::DictionaryValue* intlist_attributes = new base::DictionaryValue(); | 165 base::DictionaryValue* intlist_attributes = new base::DictionaryValue(); |
161 for (size_t i = 0; i < node.intlist_attributes.size(); ++i) { | 166 for (size_t i = 0; i < node.intlist_attributes.size(); ++i) { |
162 std::pair<ui::AXIntListAttribute, std::vector<int32> > attr = | 167 std::pair<ui::AXIntListAttribute, std::vector<int32> > attr = |
163 node.intlist_attributes[i]; | 168 node.intlist_attributes[i]; |
164 base::ListValue* intlist = new base::ListValue(); | 169 base::ListValue* intlist = new base::ListValue(); |
165 for (size_t j = 0; j < attr.second.size(); j++) | 170 for (size_t j = 0; j < attr.second.size(); j++) |
166 intlist->AppendInteger(attr.second[j]); | 171 intlist->AppendInteger(attr.second[j]); |
167 intlist_attributes->Set(ToString(attr.first), intlist); | 172 intlist_attributes->Set(ToString(attr.first), intlist); |
168 } | 173 } |
169 axNodeData->Set("intlist_attributes", intlist_attributes); | 174 axNodeData->Set("intlistAttributes", intlist_attributes); |
170 } | 175 } |
171 | 176 |
172 if (!node.string_attributes.empty()) { | 177 if (!node.string_attributes.empty()) { |
173 base::DictionaryValue* string_attributes = new base::DictionaryValue(); | 178 base::DictionaryValue* string_attributes = new base::DictionaryValue(); |
174 for (size_t i = 0; i < node.string_attributes.size(); ++i) { | 179 for (size_t i = 0; i < node.string_attributes.size(); ++i) { |
175 std::pair<ui::AXStringAttribute, std::string> attr = | 180 std::pair<ui::AXStringAttribute, std::string> attr = |
176 node.string_attributes[i]; | 181 node.string_attributes[i]; |
177 string_attributes->SetString(ToString(attr.first), attr.second); | 182 string_attributes->SetString(ToString(attr.first), attr.second); |
178 } | 183 } |
179 axNodeData->Set("string_attributes", string_attributes); | 184 axNodeData->Set("stringAttributes", string_attributes); |
180 } | 185 } |
181 | 186 |
182 base::ListValue* child_ids = new base::ListValue(); | 187 base::ListValue* child_ids = new base::ListValue(); |
183 for (size_t i = 0; i < node.child_ids.size(); ++i) { | 188 for (size_t i = 0; i < node.child_ids.size(); ++i) { |
184 child_ids->AppendInteger(node.child_ids[i]); | 189 child_ids->AppendInteger(node.child_ids[i]); |
185 } | 190 } |
186 axNodeData->Set("child_ids", child_ids); | 191 axNodeData->Set("childIDs", child_ids); |
187 | 192 |
188 nodes->Append(axNodeData); | 193 nodes->Append(axNodeData); |
189 } | 194 } |
190 | 195 |
191 content::BrowserContext* browser_context_; | 196 content::BrowserContext* browser_context_; |
192 | 197 |
193 DISALLOW_COPY_AND_ASSIGN(AutomationWebContentsObserver); | 198 DISALLOW_COPY_AND_ASSIGN(AutomationWebContentsObserver); |
194 }; | 199 }; |
195 | 200 |
196 // TODO(aboxhall/dtseng): ensure that the initial data is sent down for the tab | 201 // TODO(aboxhall/dtseng): ensure that the initial data is sent down for the tab |
(...skipping 15 matching lines...) Expand all Loading... | |
212 content::RenderWidgetHost* rwh = | 217 content::RenderWidgetHost* rwh = |
213 contents->GetRenderWidgetHostView()->GetRenderWidgetHost(); | 218 contents->GetRenderWidgetHostView()->GetRenderWidgetHost(); |
214 if (!rwh) | 219 if (!rwh) |
215 return false; | 220 return false; |
216 | 221 |
217 AutomationWebContentsObserver::CreateForWebContents(contents); | 222 AutomationWebContentsObserver::CreateForWebContents(contents); |
218 | 223 |
219 rwh->EnableTreeOnlyAccessibilityMode(); | 224 rwh->EnableTreeOnlyAccessibilityMode(); |
220 | 225 |
221 results_ = api::automation_internal::EnableCurrentTab::Results::Create( | 226 results_ = api::automation_internal::EnableCurrentTab::Results::Create( |
222 rwh->GetRoutingID()); | 227 rwh->GetProcess()->GetID(), rwh->GetRoutingID()); |
223 | 228 |
224 SendResponse(true); | 229 SendResponse(true); |
225 return true; | 230 return true; |
226 } | 231 } |
227 | 232 |
233 bool AutomationInternalPerformActionFunction::RunImpl() { | |
234 using api::automation_internal::PerformAction::Params; | |
235 scoped_ptr<Params> params(Params::Create(*args_)); | |
236 EXTENSION_FUNCTION_VALIDATE(params.get()); | |
237 | |
238 content::RenderWidgetHost* rwh = | |
239 content::RenderWidgetHost::FromID(params->args.process_id, | |
240 params->args.routing_id); | |
241 | |
242 switch (params->args.action_type) { | |
243 case api::automation_internal::ACTION_TYPE_DO_DEFAULT: | |
244 rwh->AccessibilityDoDefaultAction(params->args.automation_node_id); | |
245 break; | |
246 case api::automation_internal::ACTION_TYPE_FOCUS: | |
247 rwh->AccessibilitySetFocus(params->args.automation_node_id); | |
248 break; | |
249 case api::automation_internal::ACTION_TYPE_MAKE_VISIBLE: | |
250 rwh->AccessibilityScrollToMakeVisible(params->args.automation_node_id, | |
251 gfx::Rect()); | |
252 break; | |
253 case api::automation_internal::ACTION_TYPE_SET_SELECTION: { | |
254 extensions::api::automation_internal::SetSelectionParams selection_params; | |
255 EXTENSION_FUNCTION_VALIDATE( | |
256 extensions::api::automation_internal::SetSelectionParams::Populate( | |
257 params->opt_args.additional_properties, &selection_params)); | |
258 rwh->AccessibilitySetTextSelection(params->args.automation_node_id, | |
259 selection_params.start_index, | |
260 selection_params.end_index); | |
261 break; | |
262 } | |
263 default: | |
264 NOTREACHED(); | |
265 } | |
266 return true; | |
267 } | |
268 | |
228 } // namespace extensions | 269 } // namespace extensions |
OLD | NEW |