| 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 "content/renderer/accessibility/blink_ax_tree_source.h" | 5 #include "content/renderer/accessibility/blink_ax_tree_source.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <set> | 9 #include <set> |
| 10 | 10 |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 106 AXContentNodeData* dst) { | 106 AXContentNodeData* dst) { |
| 107 std::vector<int32_t> ids; | 107 std::vector<int32_t> ids; |
| 108 for(size_t i = 0; i < objects.size(); i++) | 108 for(size_t i = 0; i < objects.size(); i++) |
| 109 ids.push_back(objects[i].axID()); | 109 ids.push_back(objects[i].axID()); |
| 110 if (ids.size() > 0) | 110 if (ids.size() > 0) |
| 111 dst->AddIntListAttribute(attr, ids); | 111 dst->AddIntListAttribute(attr, ids); |
| 112 } | 112 } |
| 113 | 113 |
| 114 } // namespace | 114 } // namespace |
| 115 | 115 |
| 116 ScopedFreezeBlinkAXTreeSource::ScopedFreezeBlinkAXTreeSource( |
| 117 BlinkAXTreeSource* tree_source) |
| 118 : tree_source_(tree_source) { |
| 119 tree_source_->Freeze(); |
| 120 } |
| 121 |
| 122 ScopedFreezeBlinkAXTreeSource::~ScopedFreezeBlinkAXTreeSource() { |
| 123 tree_source_->Thaw(); |
| 124 } |
| 125 |
| 116 BlinkAXTreeSource::BlinkAXTreeSource(RenderFrameImpl* render_frame) | 126 BlinkAXTreeSource::BlinkAXTreeSource(RenderFrameImpl* render_frame) |
| 117 : render_frame_(render_frame), | 127 : render_frame_(render_frame), |
| 118 accessibility_focus_id_(-1) { | 128 accessibility_focus_id_(-1), |
| 119 } | 129 frozen_(false) {} |
| 120 | 130 |
| 121 BlinkAXTreeSource::~BlinkAXTreeSource() { | 131 BlinkAXTreeSource::~BlinkAXTreeSource() { |
| 122 } | 132 } |
| 123 | 133 |
| 134 void BlinkAXTreeSource::Freeze() { |
| 135 CHECK(!frozen_); |
| 136 frozen_ = true; |
| 137 |
| 138 if (render_frame_ && render_frame_->GetWebFrame()) |
| 139 document_ = render_frame_->GetWebFrame()->document(); |
| 140 else |
| 141 document_ = WebDocument(); |
| 142 |
| 143 root_ = ComputeRoot(); |
| 144 |
| 145 if (!document_.isNull()) |
| 146 focus_ = document_.focusedAccessibilityObject(); |
| 147 else |
| 148 focus_ = WebAXObject(); |
| 149 } |
| 150 |
| 151 void BlinkAXTreeSource::Thaw() { |
| 152 CHECK(frozen_); |
| 153 frozen_ = false; |
| 154 } |
| 155 |
| 124 void BlinkAXTreeSource::SetRoot(blink::WebAXObject root) { | 156 void BlinkAXTreeSource::SetRoot(blink::WebAXObject root) { |
| 125 root_ = root; | 157 CHECK(!frozen_); |
| 158 explicit_root_ = root; |
| 126 } | 159 } |
| 127 | 160 |
| 128 bool BlinkAXTreeSource::IsInTree(blink::WebAXObject node) const { | 161 bool BlinkAXTreeSource::IsInTree(blink::WebAXObject node) const { |
| 129 const blink::WebAXObject& root = GetRoot(); | 162 CHECK(frozen_); |
| 130 while (IsValid(node)) { | 163 while (IsValid(node)) { |
| 131 if (node.equals(root)) | 164 if (node.equals(root())) |
| 132 return true; | 165 return true; |
| 133 node = GetParent(node); | 166 node = GetParent(node); |
| 134 } | 167 } |
| 135 return false; | 168 return false; |
| 136 } | 169 } |
| 137 | 170 |
| 138 bool BlinkAXTreeSource::GetTreeData(AXContentTreeData* tree_data) const { | 171 bool BlinkAXTreeSource::GetTreeData(AXContentTreeData* tree_data) const { |
| 139 blink::WebDocument document = BlinkAXTreeSource::GetMainDocument(); | 172 CHECK(frozen_); |
| 140 const blink::WebAXObject& root = GetRoot(); | 173 tree_data->doctype = "html"; |
| 174 tree_data->loaded = root().isLoaded(); |
| 175 tree_data->loading_progress = root().estimatedLoadingProgress(); |
| 176 tree_data->mimetype = |
| 177 document().isXHTMLDocument() ? "text/xhtml" : "text/html"; |
| 178 tree_data->title = document().title().utf8(); |
| 179 tree_data->url = document().url().string().utf8(); |
| 141 | 180 |
| 142 tree_data->doctype = "html"; | 181 if (!focus().isNull()) |
| 143 tree_data->loaded = root.isLoaded(); | 182 tree_data->focus_id = focus().axID(); |
| 144 tree_data->loading_progress = root.estimatedLoadingProgress(); | |
| 145 tree_data->mimetype = document.isXHTMLDocument() ? "text/xhtml" : "text/html"; | |
| 146 tree_data->title = document.title().utf8(); | |
| 147 tree_data->url = document.url().string().utf8(); | |
| 148 | |
| 149 WebAXObject focus = document.focusedAccessibilityObject(); | |
| 150 if (!focus.isNull()) | |
| 151 tree_data->focus_id = focus.axID(); | |
| 152 | 183 |
| 153 WebAXObject anchor_object, focus_object; | 184 WebAXObject anchor_object, focus_object; |
| 154 int anchor_offset, focus_offset; | 185 int anchor_offset, focus_offset; |
| 155 blink::WebAXTextAffinity anchor_affinity, focus_affinity; | 186 blink::WebAXTextAffinity anchor_affinity, focus_affinity; |
| 156 root.selection(anchor_object, anchor_offset, anchor_affinity, | 187 root().selection(anchor_object, anchor_offset, anchor_affinity, focus_object, |
| 157 focus_object, focus_offset, focus_affinity); | 188 focus_offset, focus_affinity); |
| 158 if (!anchor_object.isNull() && !focus_object.isNull() && | 189 if (!anchor_object.isNull() && !focus_object.isNull() && |
| 159 anchor_offset >= 0 && focus_offset >= 0) { | 190 anchor_offset >= 0 && focus_offset >= 0) { |
| 160 int32_t anchor_id = anchor_object.axID(); | 191 int32_t anchor_id = anchor_object.axID(); |
| 161 int32_t focus_id = focus_object.axID(); | 192 int32_t focus_id = focus_object.axID(); |
| 162 tree_data->sel_anchor_object_id = anchor_id; | 193 tree_data->sel_anchor_object_id = anchor_id; |
| 163 tree_data->sel_anchor_offset = anchor_offset; | 194 tree_data->sel_anchor_offset = anchor_offset; |
| 164 tree_data->sel_focus_object_id = focus_id; | 195 tree_data->sel_focus_object_id = focus_id; |
| 165 tree_data->sel_focus_offset = focus_offset; | 196 tree_data->sel_focus_offset = focus_offset; |
| 166 tree_data->sel_anchor_affinity = AXTextAffinityFromBlink(anchor_affinity); | 197 tree_data->sel_anchor_affinity = AXTextAffinityFromBlink(anchor_affinity); |
| 167 tree_data->sel_focus_affinity = AXTextAffinityFromBlink(focus_affinity); | 198 tree_data->sel_focus_affinity = AXTextAffinityFromBlink(focus_affinity); |
| 168 } | 199 } |
| 169 | 200 |
| 170 // Get the tree ID for this frame and the parent frame. | 201 // Get the tree ID for this frame and the parent frame. |
| 171 WebLocalFrame* web_frame = document.frame(); | 202 WebLocalFrame* web_frame = document().frame(); |
| 172 if (web_frame) { | 203 if (web_frame) { |
| 173 RenderFrame* render_frame = RenderFrame::FromWebFrame(web_frame); | 204 RenderFrame* render_frame = RenderFrame::FromWebFrame(web_frame); |
| 174 tree_data->routing_id = render_frame->GetRoutingID(); | 205 tree_data->routing_id = render_frame->GetRoutingID(); |
| 175 | 206 |
| 176 // Get the tree ID for the parent frame. | 207 // Get the tree ID for the parent frame. |
| 177 blink::WebFrame* parent_web_frame = web_frame->parent(); | 208 blink::WebFrame* parent_web_frame = web_frame->parent(); |
| 178 if (parent_web_frame) { | 209 if (parent_web_frame) { |
| 179 tree_data->parent_routing_id = | 210 tree_data->parent_routing_id = |
| 180 GetRoutingIdForFrameOrProxy(parent_web_frame); | 211 GetRoutingIdForFrameOrProxy(parent_web_frame); |
| 181 } | 212 } |
| 182 } | 213 } |
| 183 | 214 |
| 184 return true; | 215 return true; |
| 185 } | 216 } |
| 186 | 217 |
| 187 blink::WebAXObject BlinkAXTreeSource::GetRoot() const { | 218 blink::WebAXObject BlinkAXTreeSource::GetRoot() const { |
| 188 if (!root_.isNull()) | 219 if (frozen_) |
| 189 return root_; | 220 return root_; |
| 190 return GetMainDocument().accessibilityObject(); | 221 else |
| 222 return ComputeRoot(); |
| 191 } | 223 } |
| 192 | 224 |
| 193 blink::WebAXObject BlinkAXTreeSource::GetFromId(int32_t id) const { | 225 blink::WebAXObject BlinkAXTreeSource::GetFromId(int32_t id) const { |
| 194 return GetMainDocument().accessibilityObjectFromID(id); | 226 return GetMainDocument().accessibilityObjectFromID(id); |
| 195 } | 227 } |
| 196 | 228 |
| 197 int32_t BlinkAXTreeSource::GetId(blink::WebAXObject node) const { | 229 int32_t BlinkAXTreeSource::GetId(blink::WebAXObject node) const { |
| 198 return node.axID(); | 230 return node.axID(); |
| 199 } | 231 } |
| 200 | 232 |
| 201 void BlinkAXTreeSource::GetChildren( | 233 void BlinkAXTreeSource::GetChildren( |
| 202 blink::WebAXObject parent, | 234 blink::WebAXObject parent, |
| 203 std::vector<blink::WebAXObject>* out_children) const { | 235 std::vector<blink::WebAXObject>* out_children) const { |
| 236 CHECK(frozen_); |
| 237 |
| 204 if (parent.role() == blink::WebAXRoleStaticText) { | 238 if (parent.role() == blink::WebAXRoleStaticText) { |
| 239 int32_t focus_id = focus().axID(); |
| 205 blink::WebAXObject ancestor = parent; | 240 blink::WebAXObject ancestor = parent; |
| 206 while (!ancestor.isDetached()) { | 241 while (!ancestor.isDetached()) { |
| 207 int32_t focus_id = GetMainDocument().focusedAccessibilityObject().axID(); | |
| 208 if (ancestor.axID() == accessibility_focus_id_ || | 242 if (ancestor.axID() == accessibility_focus_id_ || |
| 209 (ancestor.axID() == focus_id && ancestor.isEditable())) { | 243 (ancestor.axID() == focus_id && ancestor.isEditable())) { |
| 210 parent.loadInlineTextBoxes(); | 244 parent.loadInlineTextBoxes(); |
| 211 break; | 245 break; |
| 212 } | 246 } |
| 213 ancestor = ancestor.parentObject(); | 247 ancestor = ancestor.parentObject(); |
| 214 } | 248 } |
| 215 } | 249 } |
| 216 | 250 |
| 217 bool is_iframe = false; | 251 bool is_iframe = false; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 230 // As an exception, include children of an iframe element. | 264 // As an exception, include children of an iframe element. |
| 231 if (!is_iframe && !IsParentUnignoredOf(parent, child)) | 265 if (!is_iframe && !IsParentUnignoredOf(parent, child)) |
| 232 continue; | 266 continue; |
| 233 | 267 |
| 234 out_children->push_back(child); | 268 out_children->push_back(child); |
| 235 } | 269 } |
| 236 } | 270 } |
| 237 | 271 |
| 238 blink::WebAXObject BlinkAXTreeSource::GetParent( | 272 blink::WebAXObject BlinkAXTreeSource::GetParent( |
| 239 blink::WebAXObject node) const { | 273 blink::WebAXObject node) const { |
| 274 CHECK(frozen_); |
| 275 |
| 240 // Blink returns ignored objects when walking up the parent chain, | 276 // Blink returns ignored objects when walking up the parent chain, |
| 241 // we have to skip those here. Also, stop when we get to the root | 277 // we have to skip those here. Also, stop when we get to the root |
| 242 // element. | 278 // element. |
| 243 blink::WebAXObject root = GetRoot(); | |
| 244 do { | 279 do { |
| 245 if (node.equals(root)) | 280 if (node.equals(root())) |
| 246 return blink::WebAXObject(); | 281 return blink::WebAXObject(); |
| 247 node = node.parentObject(); | 282 node = node.parentObject(); |
| 248 } while (!node.isDetached() && node.accessibilityIsIgnored()); | 283 } while (!node.isDetached() && node.accessibilityIsIgnored()); |
| 249 | 284 |
| 250 return node; | 285 return node; |
| 251 } | 286 } |
| 252 | 287 |
| 253 bool BlinkAXTreeSource::IsValid(blink::WebAXObject node) const { | 288 bool BlinkAXTreeSource::IsValid(blink::WebAXObject node) const { |
| 254 return !node.isDetached(); // This also checks if it's null. | 289 return !node.isDetached(); // This also checks if it's null. |
| 255 } | 290 } |
| (...skipping 435 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 691 dst->AddIntAttribute(ui::AX_ATTR_SCROLL_X_MIN, minScrollOffset.x()); | 726 dst->AddIntAttribute(ui::AX_ATTR_SCROLL_X_MIN, minScrollOffset.x()); |
| 692 dst->AddIntAttribute(ui::AX_ATTR_SCROLL_Y_MIN, minScrollOffset.y()); | 727 dst->AddIntAttribute(ui::AX_ATTR_SCROLL_Y_MIN, minScrollOffset.y()); |
| 693 | 728 |
| 694 const gfx::Point& maxScrollOffset = src.maximumScrollOffset(); | 729 const gfx::Point& maxScrollOffset = src.maximumScrollOffset(); |
| 695 dst->AddIntAttribute(ui::AX_ATTR_SCROLL_X_MAX, maxScrollOffset.x()); | 730 dst->AddIntAttribute(ui::AX_ATTR_SCROLL_X_MAX, maxScrollOffset.x()); |
| 696 dst->AddIntAttribute(ui::AX_ATTR_SCROLL_Y_MAX, maxScrollOffset.y()); | 731 dst->AddIntAttribute(ui::AX_ATTR_SCROLL_Y_MAX, maxScrollOffset.y()); |
| 697 } | 732 } |
| 698 } | 733 } |
| 699 | 734 |
| 700 blink::WebDocument BlinkAXTreeSource::GetMainDocument() const { | 735 blink::WebDocument BlinkAXTreeSource::GetMainDocument() const { |
| 701 if (render_frame_ && render_frame_->GetWebFrame()) | 736 CHECK(frozen_); |
| 702 return render_frame_->GetWebFrame()->document(); | 737 return document_; |
| 703 return WebDocument(); | 738 } |
| 739 |
| 740 WebAXObject BlinkAXTreeSource::ComputeRoot() const { |
| 741 if (!explicit_root_.isNull()) |
| 742 return explicit_root_; |
| 743 |
| 744 if (!render_frame_ || !render_frame_->GetWebFrame()) |
| 745 return WebAXObject(); |
| 746 |
| 747 WebDocument document = render_frame_->GetWebFrame()->document(); |
| 748 if (!document.isNull()) |
| 749 return document.accessibilityObject(); |
| 750 |
| 751 return WebAXObject(); |
| 704 } | 752 } |
| 705 | 753 |
| 706 } // namespace content | 754 } // namespace content |
| OLD | NEW |