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. 4 5 #include "chrome/browser/extensions/api/automation_internal/automation_util.h" 6 7 #include <string> 8 #include <utility> 9 10 #include "base/values.h" 11 #include "chrome/common/extensions/api/automation_internal.h" 12 #include "extensions/browser/event_router.h" 13 #include "ui/accessibility/ax_enums.h" 14 #include "ui/accessibility/ax_node_data.h" 15 16 namespace extensions { 17 18 namespace { 19 20 void PopulateNodeData(const ui::AXNodeData& node_data, 21 linked_ptr< api::automation_internal::AXNodeData>& out_node_data) { 22 out_node_data->id = node_data.id; 23 out_node_data->role = ToString(node_data.role); 24 25 uint32 state_pos = 0, state_shifter = node_data.state; 26 while (state_shifter) { 27 if (state_shifter & 1) { 28 out_node_data->state.additional_properties.SetBoolean( 29 ToString(static_cast<ui::AXState>(state_pos)), true); 30 } 31 state_shifter = state_shifter >> 1; 32 state_pos++; 33 } 34 35 out_node_data->location.left = node_data.location.x(); 36 out_node_data->location.top = node_data.location.y(); 37 out_node_data->location.width = node_data.location.width(); 38 out_node_data->location.height = node_data.location.height(); 39 40 if (!node_data.bool_attributes.empty()) { 41 out_node_data->bool_attributes.reset( 42 new api::automation_internal::AXNodeData::BoolAttributes()); 43 for (size_t i = 0; i < node_data.bool_attributes.size(); ++i) { 44 std::pair<ui::AXBoolAttribute, bool> attr = 45 node_data.bool_attributes[i]; 46 out_node_data->bool_attributes->additional_properties.SetBoolean( 47 ToString(attr.first), attr.second); 48 } 49 } 50 51 if (!node_data.float_attributes.empty()) { 52 out_node_data->float_attributes.reset( 53 new api::automation_internal::AXNodeData::FloatAttributes()); 54 for (size_t i = 0; i < node_data.float_attributes.size(); ++i) { 55 std::pair<ui::AXFloatAttribute, float> attr = 56 node_data.float_attributes[i]; 57 out_node_data->float_attributes->additional_properties.SetDouble( 58 ToString(attr.first), attr.second); 59 } 60 } 61 62 if (!node_data.html_attributes.empty()) { 63 out_node_data->html_attributes.reset( 64 new api::automation_internal::AXNodeData::HtmlAttributes()); 65 for (size_t i = 0; i < node_data.html_attributes.size(); ++i) { 66 std::pair<std::string, std::string> attr = node_data.html_attributes[i]; 67 out_node_data->html_attributes->additional_properties.SetString( 68 attr.first, attr.second); 69 } 70 } 71 72 if (!node_data.int_attributes.empty()) { 73 out_node_data->int_attributes.reset( 74 new api::automation_internal::AXNodeData::IntAttributes()); 75 for (size_t i = 0; i < node_data.int_attributes.size(); ++i) { 76 std::pair<ui::AXIntAttribute, int> attr = node_data.int_attributes[i]; 77 out_node_data->int_attributes->additional_properties.SetInteger( 78 ToString(attr.first), attr.second); 79 } 80 } 81 82 if (!node_data.intlist_attributes.empty()) { 83 out_node_data->intlist_attributes.reset( 84 new api::automation_internal::AXNodeData::IntlistAttributes()); 85 for (size_t i = 0; i < node_data.intlist_attributes.size(); ++i) { 86 std::pair<ui::AXIntListAttribute, std::vector<int32> > attr = 87 node_data.intlist_attributes[i]; 88 base::ListValue* intlist = new base::ListValue(); 89 for (size_t j = 0; j < attr.second.size(); ++j) 90 intlist->AppendInteger(attr.second[j]); 91 out_node_data->intlist_attributes->additional_properties.Set( 92 ToString(attr.first), intlist); 93 } 94 } 95 96 if (!node_data.string_attributes.empty()) { 97 out_node_data->string_attributes.reset( 98 new api::automation_internal::AXNodeData::StringAttributes()); 99 for (size_t i = 0; i < node_data.string_attributes.size(); ++i) { 100 std::pair<ui::AXStringAttribute, std::string> attr = 101 node_data.string_attributes[i]; 102 out_node_data->string_attributes->additional_properties.SetString( 103 ToString(attr.first), attr.second); 104 } 105 } 106 107 for (size_t i = 0; i < node_data.child_ids.size(); ++i) { 108 out_node_data->child_ids.push_back(node_data.child_ids[i]); 109 } 110 } 111 112 void DispatchEventInternal(content::BrowserContext* context, 113 const std::string& event_name, 114 scoped_ptr<base::ListValue> args) { 115 if (context && EventRouter::Get(context)) { 116 scoped_ptr<Event> event(new Event(event_name, args.Pass())); 117 event->restrict_to_browser_context = context; 118 EventRouter::Get(context)->BroadcastEvent(event.Pass()); 119 } 120 } 121 122 } // namespace 123 124 namespace automation_util { 125 126 void DispatchAccessibilityEventsToAutomation( 127 const std::vector<content::AXEventNotificationDetails>& details, 128 content::BrowserContext* browser_context) { 129 using api::automation_internal::AXEventParams; 130 131 std::vector<content::AXEventNotificationDetails>::const_iterator iter = 132 details.begin(); 133 for (; iter != details.end(); ++iter) { 134 const content::AXEventNotificationDetails& event = *iter; 135 136 AXEventParams ax_tree_update; 137 ax_tree_update.process_id = event.process_id; 138 ax_tree_update.routing_id = event.routing_id; 139 ax_tree_update.event_type = ToString(iter->event_type); 140 ax_tree_update.target_id = event.id; 141 142 for (size_t i = 0; i < event.nodes.size(); ++i) { 143 linked_ptr<api::automation_internal::AXNodeData> out_node( 144 new api::automation_internal::AXNodeData()); 145 PopulateNodeData(event.nodes[i], out_node); 146 ax_tree_update.nodes.push_back(out_node); 147 } 148 149 // TODO(dtseng/aboxhall): Why are we sending only one update at a time? We 150 // should match the behavior from renderer -> browser and send a 151 // collection of tree updates over (to the extension); see 152 // |AccessibilityHostMsg_EventParams| and |AccessibilityHostMsg_Events|. 153 DispatchEventInternal(browser_context, 154 api::automation_internal::OnAccessibilityEvent::kEventName, 155 api::automation_internal::OnAccessibilityEvent::Create(ax_tree_update)); 156 } 157 } 158 159 } // namespace automation_util 160 161 } // namespace extensions 162