Chromium Code Reviews| 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 |