Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(497)

Side by Side Diff: chrome/browser/extensions/api/automation_internal/automation_internal_api.cc

Issue 203753002: Implement actions for Automation API. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Lots of style cleanup. Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698