Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2017 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/chromeos/arc/accessibility/ax_tree_source_arc.h" | |
| 6 | |
| 7 #include "chrome/browser/extensions/api/automation_internal/automation_event_rou ter.h" | |
| 8 #include "chrome/browser/ui/aura/accessibility/automation_manager_aura.h" | |
| 9 #include "chrome/common/extensions/chrome_extension_messages.h" | |
| 10 #include "components/exo/wm_helper.h" | |
| 11 #include "ui/accessibility/ax_tree_id_registry.h" | |
| 12 #include "ui/aura/window.h" | |
| 13 | |
| 14 namespace { | |
| 15 | |
| 16 ui::AXEvent ToAXEvent(arc::mojom::AccessibilityEventType arc_event_type) { | |
| 17 switch (arc_event_type) { | |
| 18 case arc::mojom::AccessibilityEventType::VIEW_FOCUSED: | |
| 19 case arc::mojom::AccessibilityEventType::VIEW_ACCESSIBILITY_FOCUSED: | |
| 20 return ui::AX_EVENT_FOCUS; | |
| 21 case arc::mojom::AccessibilityEventType::VIEW_ACCESSIBILITY_FOCUS_CLEARED: | |
| 22 return ui::AX_EVENT_BLUR; | |
| 23 case arc::mojom::AccessibilityEventType::VIEW_CLICKED: | |
| 24 case arc::mojom::AccessibilityEventType::VIEW_LONG_CLICKED: | |
| 25 return ui::AX_EVENT_CLICKED; | |
| 26 case arc::mojom::AccessibilityEventType::VIEW_TEXT_CHANGED: | |
| 27 return ui::AX_EVENT_TEXT_CHANGED; | |
| 28 case arc::mojom::AccessibilityEventType::VIEW_TEXT_SELECTION_CHANGED: | |
| 29 return ui::AX_EVENT_TEXT_SELECTION_CHANGED; | |
| 30 case arc::mojom::AccessibilityEventType::WINDOW_STATE_CHANGED: | |
| 31 case arc::mojom::AccessibilityEventType::NOTIFICATION_STATE_CHANGED: | |
| 32 case arc::mojom::AccessibilityEventType::WINDOW_CONTENT_CHANGED: | |
| 33 case arc::mojom::AccessibilityEventType::WINDOWS_CHANGED: | |
| 34 return ui::AX_EVENT_LAYOUT_COMPLETE; | |
| 35 case arc::mojom::AccessibilityEventType::VIEW_HOVER_ENTER: | |
| 36 return ui::AX_EVENT_FOCUS; | |
| 37 case arc::mojom::AccessibilityEventType::ANNOUNCEMENT: | |
| 38 return ui::AX_EVENT_ALERT; | |
| 39 case arc::mojom::AccessibilityEventType::VIEW_SELECTED: | |
| 40 case arc::mojom::AccessibilityEventType::VIEW_HOVER_EXIT: | |
| 41 case arc::mojom::AccessibilityEventType::TOUCH_EXPLORATION_GESTURE_START: | |
| 42 case arc::mojom::AccessibilityEventType::TOUCH_EXPLORATION_GESTURE_END: | |
| 43 case arc::mojom::AccessibilityEventType::VIEW_SCROLLED: | |
| 44 case arc::mojom::AccessibilityEventType:: | |
| 45 VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY: | |
| 46 case arc::mojom::AccessibilityEventType::GESTURE_DETECTION_START: | |
| 47 case arc::mojom::AccessibilityEventType::GESTURE_DETECTION_END: | |
| 48 case arc::mojom::AccessibilityEventType::TOUCH_INTERACTION_START: | |
| 49 case arc::mojom::AccessibilityEventType::TOUCH_INTERACTION_END: | |
| 50 case arc::mojom::AccessibilityEventType::VIEW_CONTEXT_CLICKED: | |
| 51 case arc::mojom::AccessibilityEventType::ASSIST_READING_CONTEXT: | |
| 52 return ui::AX_EVENT_CHILDREN_CHANGED; | |
| 53 default: | |
| 54 return ui::AX_EVENT_CHILDREN_CHANGED; | |
| 55 } | |
| 56 return ui::AX_EVENT_CHILDREN_CHANGED; | |
| 57 } | |
| 58 | |
| 59 } // namespace | |
| 60 | |
| 61 namespace arc { | |
| 62 | |
| 63 AXTreeSourceArc::AXTreeSourceArc() | |
| 64 : id_(ui::AXTreeIDRegistry::GetInstance()->CreateID()), | |
| 65 current_tree_serializer_(new AXTreeArcSerializer(this)), | |
| 66 root_id_(-1), | |
| 67 focused_node_id_(-1) { | |
| 68 set_owned_by_client(); | |
| 69 SetFocusBehavior(views::View::FocusBehavior::ALWAYS); | |
| 70 } | |
| 71 | |
| 72 AXTreeSourceArc::~AXTreeSourceArc() { | |
| 73 Reset(); | |
| 74 } | |
| 75 | |
| 76 void AXTreeSourceArc::NotifyAccessibilityEvent( | |
| 77 mojom::AccessibilityEventData* event_data) { | |
| 78 tree_map_.clear(); | |
| 79 parent_map_.clear(); | |
| 80 for (size_t i = 0; i < event_data->nodeData.size(); ++i) { | |
| 81 for (size_t j = 0; j < event_data->nodeData[i]->childIds.size(); ++j) | |
| 82 parent_map_[event_data->nodeData[i]->childIds[j]] = | |
| 83 event_data->nodeData[i]->id; | |
| 84 } | |
| 85 | |
| 86 for (size_t i = 0; i < event_data->nodeData.size(); ++i) { | |
| 87 int32_t id = event_data->nodeData[i]->id; | |
| 88 tree_map_[id] = event_data->nodeData[i].get(); | |
| 89 if (parent_map_.find(id) == parent_map_.end()) | |
| 90 root_id_ = id; | |
|
dmazzoni
2017/02/09 01:18:09
Any other clue that we have the root?
Maybe asser
yawano
2017/02/09 10:55:29
Can we simply force that the first element in the
| |
| 91 } | |
| 92 | |
| 93 ExtensionMsg_AccessibilityEventParams params; | |
| 94 current_tree_serializer_->SerializeChanges(GetFromId(event_data->sourceId), | |
| 95 ¶ms.update); | |
| 96 params.tree_id = id_; | |
| 97 params.id = event_data->sourceId; | |
| 98 params.event_type = ToAXEvent(event_data->eventType); | |
| 99 if (params.event_type == ui::AX_EVENT_FOCUS) | |
| 100 focused_node_id_ = params.id; | |
| 101 | |
| 102 extensions::AutomationEventRouter* router = | |
| 103 extensions::AutomationEventRouter::GetInstance(); | |
| 104 router->DispatchAccessibilityEvent(params); | |
| 105 } | |
| 106 | |
| 107 bool AXTreeSourceArc::GetTreeData(ui::AXTreeData* data) const { | |
| 108 data->tree_id = id_; | |
| 109 if (focused_node_id_ >= 0) | |
| 110 data->focus_id = focused_node_id_; | |
| 111 return true; | |
| 112 } | |
| 113 | |
| 114 mojom::AccessibilityNodeInfoData* AXTreeSourceArc::GetRoot() const { | |
| 115 mojom::AccessibilityNodeInfoData* root = GetFromId(root_id_); | |
| 116 return root; | |
| 117 } | |
| 118 | |
| 119 mojom::AccessibilityNodeInfoData* AXTreeSourceArc::GetFromId(int32_t id) const { | |
| 120 auto it = tree_map_.find(id); | |
| 121 if (it == tree_map_.end()) | |
| 122 return nullptr; | |
| 123 return it->second; | |
| 124 } | |
| 125 | |
| 126 int32_t AXTreeSourceArc::GetId(mojom::AccessibilityNodeInfoData* node) const { | |
| 127 if (!node) | |
| 128 return -1; | |
| 129 return node->id; | |
| 130 } | |
| 131 | |
| 132 void AXTreeSourceArc::GetChildren( | |
| 133 mojom::AccessibilityNodeInfoData* node, | |
| 134 std::vector<mojom::AccessibilityNodeInfoData*>* out_children) const { | |
| 135 if (!node) | |
| 136 return; | |
| 137 for (size_t i = 0; i < node->childIds.size(); ++i) { | |
| 138 out_children->push_back(GetFromId(node->childIds[i])); | |
| 139 } | |
| 140 } | |
| 141 | |
| 142 mojom::AccessibilityNodeInfoData* AXTreeSourceArc::GetParent( | |
| 143 mojom::AccessibilityNodeInfoData* node) const { | |
| 144 if (!node) | |
| 145 return nullptr; | |
| 146 auto it = parent_map_.find(node->id); | |
| 147 if (it != parent_map_.end()) | |
| 148 return GetFromId(it->second); | |
| 149 return nullptr; | |
| 150 } | |
| 151 | |
| 152 bool AXTreeSourceArc::IsValid(mojom::AccessibilityNodeInfoData* node) const { | |
| 153 return node; | |
| 154 } | |
| 155 | |
| 156 bool AXTreeSourceArc::IsEqual(mojom::AccessibilityNodeInfoData* node1, | |
| 157 mojom::AccessibilityNodeInfoData* node2) const { | |
| 158 if (!node1 || !node2) | |
| 159 return false; | |
| 160 return node1->id == node2->id; | |
| 161 } | |
| 162 | |
| 163 mojom::AccessibilityNodeInfoData* AXTreeSourceArc::GetNull() const { | |
| 164 return nullptr; | |
| 165 } | |
| 166 | |
| 167 void AXTreeSourceArc::SerializeNode(mojom::AccessibilityNodeInfoData* node, | |
| 168 ui::AXNodeData* out_data) const { | |
| 169 if (!node) | |
| 170 return; | |
| 171 out_data->id = node->id; | |
| 172 out_data->state = 0; | |
| 173 if (!node->text.empty()) | |
| 174 out_data->SetName(node->text); | |
| 175 else if (!node->contentDescription.empty()) | |
| 176 out_data->SetName(node->contentDescription); | |
| 177 | |
| 178 int32_t id = node->id; | |
| 179 if (id == root_id_) | |
| 180 out_data->role = ui::AX_ROLE_ROOT_WEB_AREA; | |
| 181 else if (!node->text.empty()) | |
| 182 out_data->role = ui::AX_ROLE_STATIC_TEXT; | |
| 183 else | |
| 184 out_data->role = ui::AX_ROLE_DIV; | |
| 185 | |
| 186 exo::WMHelper* wmHelper = exo::WMHelper::GetInstance(); | |
| 187 aura::Window* focused_window = wmHelper->GetFocusedWindow(); | |
|
dmazzoni
2017/02/09 01:18:09
Maybe try to refactor this out and not call it on
| |
| 188 gfx::Rect bounds_in_screen = node->boundsInScreen; | |
| 189 if (focused_window) { | |
| 190 aura::Window* toplevel_window = focused_window->GetToplevelWindow(); | |
| 191 bounds_in_screen = gfx::ScaleToEnclosingRect( | |
| 192 bounds_in_screen, | |
| 193 1.0f / toplevel_window->layer()->device_scale_factor()); | |
| 194 } | |
| 195 out_data->location.SetRect(bounds_in_screen.x(), bounds_in_screen.y(), | |
| 196 bounds_in_screen.width(), | |
| 197 bounds_in_screen.height()); | |
| 198 } | |
| 199 | |
| 200 void AXTreeSourceArc::GetAccessibleNodeData(ui::AXNodeData* node_data) { | |
| 201 node_data->AddIntAttribute(ui::AX_ATTR_CHILD_TREE_ID, id_); | |
| 202 node_data->SetName("ExoShell"); | |
| 203 } | |
| 204 | |
| 205 void AXTreeSourceArc::Reset() { | |
| 206 tree_map_.clear(); | |
| 207 parent_map_.clear(); | |
| 208 current_tree_serializer_.reset(new AXTreeArcSerializer(this)); | |
| 209 extensions::AutomationEventRouter* router = | |
| 210 extensions::AutomationEventRouter::GetInstance(); | |
| 211 router->DispatchTreeDestroyedEvent(id_, nullptr); | |
| 212 } | |
| 213 | |
| 214 } // namespace arc | |
| OLD | NEW |