| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/renderer_accessibility_complete.h" | 5 #include "content/renderer/accessibility/renderer_accessibility_complete.h" |
| 6 | 6 |
| 7 #include <queue> | 7 #include <queue> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/message_loop/message_loop.h" | 10 #include "base/message_loop/message_loop.h" |
| 11 #include "content/renderer/accessibility/accessibility_node_serializer.h" | 11 #include "content/renderer/accessibility/accessibility_node_serializer.h" |
| 12 #include "content/renderer/accessibility/blink_ax_enum_conversion.h" |
| 12 #include "content/renderer/render_view_impl.h" | 13 #include "content/renderer/render_view_impl.h" |
| 13 #include "third_party/WebKit/public/web/WebAXObject.h" | 14 #include "third_party/WebKit/public/web/WebAXObject.h" |
| 14 #include "third_party/WebKit/public/web/WebDocument.h" | 15 #include "third_party/WebKit/public/web/WebDocument.h" |
| 15 #include "third_party/WebKit/public/web/WebFrame.h" | 16 #include "third_party/WebKit/public/web/WebFrame.h" |
| 16 #include "third_party/WebKit/public/web/WebInputElement.h" | 17 #include "third_party/WebKit/public/web/WebInputElement.h" |
| 17 #include "third_party/WebKit/public/web/WebNode.h" | 18 #include "third_party/WebKit/public/web/WebNode.h" |
| 18 #include "third_party/WebKit/public/web/WebView.h" | 19 #include "third_party/WebKit/public/web/WebView.h" |
| 20 #include "ui/accessibility/ax_tree.h" |
| 19 | 21 |
| 20 using blink::WebAXObject; | 22 using blink::WebAXObject; |
| 21 using blink::WebDocument; | 23 using blink::WebDocument; |
| 22 using blink::WebFrame; | 24 using blink::WebFrame; |
| 23 using blink::WebNode; | 25 using blink::WebNode; |
| 24 using blink::WebPoint; | 26 using blink::WebPoint; |
| 25 using blink::WebRect; | 27 using blink::WebRect; |
| 26 using blink::WebSize; | 28 using blink::WebSize; |
| 27 using blink::WebView; | 29 using blink::WebView; |
| 28 | 30 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 42 // APIs that compute the bounds of a range of text, it's a waste to | 44 // APIs that compute the bounds of a range of text, it's a waste to |
| 43 // include these in the AX tree. | 45 // include these in the AX tree. |
| 44 WebAXObject::enableInlineTextBoxAccessibility(); | 46 WebAXObject::enableInlineTextBoxAccessibility(); |
| 45 #endif | 47 #endif |
| 46 | 48 |
| 47 const WebDocument& document = GetMainDocument(); | 49 const WebDocument& document = GetMainDocument(); |
| 48 if (!document.isNull()) { | 50 if (!document.isNull()) { |
| 49 // It's possible that the webview has already loaded a webpage without | 51 // It's possible that the webview has already loaded a webpage without |
| 50 // accessibility being enabled. Initialize the browser's cached | 52 // accessibility being enabled. Initialize the browser's cached |
| 51 // accessibility tree by sending it a notification. | 53 // accessibility tree by sending it a notification. |
| 52 HandleWebAccessibilityEvent(document.accessibilityObject(), | 54 HandleAXEvent(document.accessibilityObject(), |
| 53 blink::WebAXEventLayoutComplete); | 55 ui::AX_EVENT_LAYOUT_COMPLETE); |
| 54 } | 56 } |
| 55 } | 57 } |
| 56 | 58 |
| 57 RendererAccessibilityComplete::~RendererAccessibilityComplete() { | 59 RendererAccessibilityComplete::~RendererAccessibilityComplete() { |
| 58 if (browser_root_) { | 60 if (browser_root_) { |
| 59 ClearBrowserTreeNode(browser_root_); | 61 ClearBrowserTreeNode(browser_root_); |
| 60 browser_id_map_.erase(browser_root_->id); | 62 browser_id_map_.erase(browser_root_->id); |
| 61 delete browser_root_; | 63 delete browser_root_; |
| 62 } | 64 } |
| 63 DCHECK(browser_id_map_.empty()); | 65 DCHECK(browser_id_map_.empty()); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 85 } | 87 } |
| 86 | 88 |
| 87 void RendererAccessibilityComplete::FocusedNodeChanged(const WebNode& node) { | 89 void RendererAccessibilityComplete::FocusedNodeChanged(const WebNode& node) { |
| 88 const WebDocument& document = GetMainDocument(); | 90 const WebDocument& document = GetMainDocument(); |
| 89 if (document.isNull()) | 91 if (document.isNull()) |
| 90 return; | 92 return; |
| 91 | 93 |
| 92 if (node.isNull()) { | 94 if (node.isNull()) { |
| 93 // When focus is cleared, implicitly focus the document. | 95 // When focus is cleared, implicitly focus the document. |
| 94 // TODO(dmazzoni): Make WebKit send this notification instead. | 96 // TODO(dmazzoni): Make WebKit send this notification instead. |
| 95 HandleWebAccessibilityEvent(document.accessibilityObject(), | 97 HandleAXEvent(document.accessibilityObject(), ui::AX_EVENT_BLUR); |
| 96 blink::WebAXEventBlur); | |
| 97 } | 98 } |
| 98 } | 99 } |
| 99 | 100 |
| 100 void RendererAccessibilityComplete::DidFinishLoad(blink::WebFrame* frame) { | 101 void RendererAccessibilityComplete::DidFinishLoad(blink::WebFrame* frame) { |
| 101 const WebDocument& document = GetMainDocument(); | 102 const WebDocument& document = GetMainDocument(); |
| 102 if (document.isNull()) | 103 if (document.isNull()) |
| 103 return; | 104 return; |
| 104 | 105 |
| 105 // Check to see if the root accessibility object has changed, to work | 106 // Check to see if the root accessibility object has changed, to work |
| 106 // around WebKit bugs that cause AXObjectCache to be cleared | 107 // around WebKit bugs that cause AXObjectCache to be cleared |
| 107 // unnecessarily. | 108 // unnecessarily. |
| 108 // TODO(dmazzoni): remove this once rdar://5794454 is fixed. | 109 // TODO(dmazzoni): remove this once rdar://5794454 is fixed. |
| 109 WebAXObject new_root = document.accessibilityObject(); | 110 WebAXObject new_root = document.accessibilityObject(); |
| 110 if (!browser_root_ || new_root.axID() != browser_root_->id) | 111 if (!browser_root_ || new_root.axID() != browser_root_->id) |
| 111 HandleWebAccessibilityEvent(new_root, blink::WebAXEventLayoutComplete); | 112 HandleAXEvent(new_root, ui::AX_EVENT_LAYOUT_COMPLETE); |
| 112 } | 113 } |
| 113 | 114 |
| 115 |
| 114 void RendererAccessibilityComplete::HandleWebAccessibilityEvent( | 116 void RendererAccessibilityComplete::HandleWebAccessibilityEvent( |
| 115 const blink::WebAXObject& obj, | 117 const blink::WebAXObject& obj, blink::WebAXEvent event) { |
| 116 blink::WebAXEvent event) { | 118 HandleAXEvent(obj, AXEventFromBlink(event)); |
| 119 } |
| 120 |
| 121 void RendererAccessibilityComplete::HandleAXEvent( |
| 122 const blink::WebAXObject& obj, ui::AXEvent event) { |
| 117 const WebDocument& document = GetMainDocument(); | 123 const WebDocument& document = GetMainDocument(); |
| 118 if (document.isNull()) | 124 if (document.isNull()) |
| 119 return; | 125 return; |
| 120 | 126 |
| 121 gfx::Size scroll_offset = document.frame()->scrollOffset(); | 127 gfx::Size scroll_offset = document.frame()->scrollOffset(); |
| 122 if (scroll_offset != last_scroll_offset_) { | 128 if (scroll_offset != last_scroll_offset_) { |
| 123 // Make sure the browser is always aware of the scroll position of | 129 // Make sure the browser is always aware of the scroll position of |
| 124 // the root document element by posting a generic notification that | 130 // the root document element by posting a generic notification that |
| 125 // will update it. | 131 // will update it. |
| 126 // TODO(dmazzoni): remove this as soon as | 132 // TODO(dmazzoni): remove this as soon as |
| 127 // https://bugs.webkit.org/show_bug.cgi?id=73460 is fixed. | 133 // https://bugs.webkit.org/show_bug.cgi?id=73460 is fixed. |
| 128 last_scroll_offset_ = scroll_offset; | 134 last_scroll_offset_ = scroll_offset; |
| 129 if (!obj.equals(document.accessibilityObject())) { | 135 if (!obj.equals(document.accessibilityObject())) { |
| 130 HandleWebAccessibilityEvent( | 136 HandleAXEvent(document.accessibilityObject(), |
| 131 document.accessibilityObject(), | 137 ui::AX_EVENT_LAYOUT_COMPLETE); |
| 132 blink::WebAXEventLayoutComplete); | |
| 133 } | 138 } |
| 134 } | 139 } |
| 135 | 140 |
| 136 // Add the accessibility object to our cache and ensure it's valid. | 141 // Add the accessibility object to our cache and ensure it's valid. |
| 137 AccessibilityHostMsg_EventParams acc_event; | 142 AccessibilityHostMsg_EventParams acc_event; |
| 138 acc_event.id = obj.axID(); | 143 acc_event.id = obj.axID(); |
| 139 acc_event.event_type = event; | 144 acc_event.event_type = event; |
| 140 | 145 |
| 141 // Discard duplicate accessibility events. | 146 // Discard duplicate accessibility events. |
| 142 for (uint32 i = 0; i < pending_events_.size(); ++i) { | 147 for (uint32 i = 0; i < pending_events_.size(); ++i) { |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 194 | 199 |
| 195 WebAXObject obj = document.accessibilityObjectFromID( | 200 WebAXObject obj = document.accessibilityObjectFromID( |
| 196 event.id); | 201 event.id); |
| 197 if (!obj.updateBackingStoreAndCheckValidity()) | 202 if (!obj.updateBackingStoreAndCheckValidity()) |
| 198 continue; | 203 continue; |
| 199 | 204 |
| 200 // When we get a "selected children changed" event, WebKit | 205 // When we get a "selected children changed" event, WebKit |
| 201 // doesn't also send us events for each child that changed | 206 // doesn't also send us events for each child that changed |
| 202 // selection state, so make sure we re-send that whole subtree. | 207 // selection state, so make sure we re-send that whole subtree. |
| 203 if (event.event_type == | 208 if (event.event_type == |
| 204 blink::WebAXEventSelectedChildrenChanged) { | 209 ui::AX_EVENT_SELECTED_CHILDREN_CHANGED) { |
| 205 base::hash_map<int32, BrowserTreeNode*>::iterator iter = | 210 base::hash_map<int32, BrowserTreeNode*>::iterator iter = |
| 206 browser_id_map_.find(obj.axID()); | 211 browser_id_map_.find(obj.axID()); |
| 207 if (iter != browser_id_map_.end()) | 212 if (iter != browser_id_map_.end()) |
| 208 ClearBrowserTreeNode(iter->second); | 213 ClearBrowserTreeNode(iter->second); |
| 209 } | 214 } |
| 210 | 215 |
| 211 // The browser may not have this object yet, for example if we get a | 216 // The browser may not have this object yet, for example if we get a |
| 212 // event on an object that was recently added, or if we get a | 217 // event on an object that was recently added, or if we get a |
| 213 // event on a node before the page has loaded. Work our way | 218 // event on a node before the page has loaded. Work our way |
| 214 // up the parent chain until we find a node the browser has, or until | 219 // up the parent chain until we find a node the browser has, or until |
| 215 // we reach the root. | 220 // we reach the root. |
| 216 WebAXObject root_object = document.accessibilityObject(); | 221 WebAXObject root_object = document.accessibilityObject(); |
| 217 int root_id = root_object.axID(); | 222 int root_id = root_object.axID(); |
| 218 while (browser_id_map_.find(obj.axID()) == browser_id_map_.end() && | 223 while (browser_id_map_.find(obj.axID()) == browser_id_map_.end() && |
| 219 !obj.isDetached() && | 224 !obj.isDetached() && |
| 220 obj.axID() != root_id) { | 225 obj.axID() != root_id) { |
| 221 obj = obj.parentObject(); | 226 obj = obj.parentObject(); |
| 222 if (event.event_type == | 227 if (event.event_type == |
| 223 blink::WebAXEventChildrenChanged) { | 228 ui::AX_EVENT_CHILDREN_CHANGED) { |
| 224 event.id = obj.axID(); | 229 event.id = obj.axID(); |
| 225 } | 230 } |
| 226 } | 231 } |
| 227 | 232 |
| 228 if (obj.isDetached()) { | 233 if (obj.isDetached()) { |
| 229 #ifndef NDEBUG | 234 #ifndef NDEBUG |
| 230 if (logging_) | 235 LOG(WARNING) << "Got event on object that is invalid or has" |
| 231 LOG(WARNING) << "Got event on object that is invalid or has" | 236 << " invalid ancestor. Id: " << obj.axID(); |
| 232 << " invalid ancestor. Id: " << obj.axID(); | |
| 233 #endif | 237 #endif |
| 234 continue; | 238 continue; |
| 235 } | 239 } |
| 236 | 240 |
| 237 // Another potential problem is that this event may be on an | 241 // Another potential problem is that this event may be on an |
| 238 // object that is detached from the tree. Determine if this node is not a | 242 // object that is detached from the tree. Determine if this node is not a |
| 239 // child of its parent, and if so move the event to the parent. | 243 // child of its parent, and if so move the event to the parent. |
| 240 // TODO(dmazzoni): see if this can be removed after | 244 // TODO(dmazzoni): see if this can be removed after |
| 241 // https://bugs.webkit.org/show_bug.cgi?id=68466 is fixed. | 245 // https://bugs.webkit.org/show_bug.cgi?id=68466 is fixed. |
| 242 if (obj.axID() != root_id) { | 246 if (obj.axID() != root_id) { |
| (...skipping 26 matching lines...) Expand all Loading... |
| 269 root_object.startCachingComputedObjectAttributesUntilTreeMutates(); | 273 root_object.startCachingComputedObjectAttributesUntilTreeMutates(); |
| 270 | 274 |
| 271 AccessibilityHostMsg_EventParams event_msg; | 275 AccessibilityHostMsg_EventParams event_msg; |
| 272 event_msg.event_type = event.event_type; | 276 event_msg.event_type = event.event_type; |
| 273 event_msg.id = event.id; | 277 event_msg.id = event.id; |
| 274 std::set<int> ids_serialized; | 278 std::set<int> ids_serialized; |
| 275 SerializeChangedNodes(obj, &event_msg.nodes, &ids_serialized); | 279 SerializeChangedNodes(obj, &event_msg.nodes, &ids_serialized); |
| 276 event_msgs.push_back(event_msg); | 280 event_msgs.push_back(event_msg); |
| 277 | 281 |
| 278 #ifndef NDEBUG | 282 #ifndef NDEBUG |
| 279 if (logging_) { | 283 ui::AXTree tree; |
| 280 AccessibilityNodeDataTreeNode tree; | 284 ui::AXTreeUpdate update; |
| 281 MakeAccessibilityNodeDataTree(event_msg.nodes, &tree); | 285 update.nodes = event_msg.nodes; |
| 282 VLOG(0) << "Accessibility update: \n" | 286 tree.Unserialize(update); |
| 283 << "routing id=" << routing_id() | 287 VLOG(0) << "Accessibility update: \n" |
| 284 << " event=" | 288 << "routing id=" << routing_id() |
| 285 << AccessibilityEventToString(event.event_type) | 289 << " event=" |
| 286 << "\n" << tree.DebugString(true); | 290 << AccessibilityEventToString(event.event_type) |
| 287 } | 291 << "\n" << tree.ToString(); |
| 288 #endif | 292 #endif |
| 289 } | 293 } |
| 290 | 294 |
| 291 Send(new AccessibilityHostMsg_Events(routing_id(), event_msgs)); | 295 Send(new AccessibilityHostMsg_Events(routing_id(), event_msgs)); |
| 292 | 296 |
| 293 SendLocationChanges(); | 297 SendLocationChanges(); |
| 294 } | 298 } |
| 295 | 299 |
| 296 void RendererAccessibilityComplete::SendLocationChanges() { | 300 void RendererAccessibilityComplete::SendLocationChanges() { |
| 297 std::queue<WebAXObject> objs_to_explore; | 301 std::queue<WebAXObject> objs_to_explore; |
| (...skipping 30 matching lines...) Expand all Loading... |
| 328 Send(new AccessibilityHostMsg_LocationChanges(routing_id(), messages)); | 332 Send(new AccessibilityHostMsg_LocationChanges(routing_id(), messages)); |
| 329 } | 333 } |
| 330 | 334 |
| 331 RendererAccessibilityComplete::BrowserTreeNode* | 335 RendererAccessibilityComplete::BrowserTreeNode* |
| 332 RendererAccessibilityComplete::CreateBrowserTreeNode() { | 336 RendererAccessibilityComplete::CreateBrowserTreeNode() { |
| 333 return new RendererAccessibilityComplete::BrowserTreeNode(); | 337 return new RendererAccessibilityComplete::BrowserTreeNode(); |
| 334 } | 338 } |
| 335 | 339 |
| 336 void RendererAccessibilityComplete::SerializeChangedNodes( | 340 void RendererAccessibilityComplete::SerializeChangedNodes( |
| 337 const blink::WebAXObject& obj, | 341 const blink::WebAXObject& obj, |
| 338 std::vector<AccessibilityNodeData>* dst, | 342 std::vector<ui::AXNodeData>* dst, |
| 339 std::set<int>* ids_serialized) { | 343 std::set<int>* ids_serialized) { |
| 340 if (ids_serialized->find(obj.axID()) != ids_serialized->end()) | 344 if (ids_serialized->find(obj.axID()) != ids_serialized->end()) |
| 341 return; | 345 return; |
| 342 ids_serialized->insert(obj.axID()); | 346 ids_serialized->insert(obj.axID()); |
| 343 | 347 |
| 344 // This method has three responsibilities: | 348 // This method has three responsibilities: |
| 345 // 1. Serialize |obj| into an AccessibilityNodeData, and append it to | 349 // 1. Serialize |obj| into an ui::AXNodeData, and append it to |
| 346 // the end of the |dst| vector to be send to the browser process. | 350 // the end of the |dst| vector to be send to the browser process. |
| 347 // 2. Determine if |obj| has any new children that the browser doesn't | 351 // 2. Determine if |obj| has any new children that the browser doesn't |
| 348 // know about yet, and call SerializeChangedNodes recursively on those. | 352 // know about yet, and call SerializeChangedNodes recursively on those. |
| 349 // 3. Update our internal data structure that keeps track of what nodes | 353 // 3. Update our internal data structure that keeps track of what nodes |
| 350 // the browser knows about. | 354 // the browser knows about. |
| 351 | 355 |
| 352 // First, find the BrowserTreeNode for this id in our data structure where | 356 // First, find the BrowserTreeNode for this id in our data structure where |
| 353 // we keep track of what accessibility objects the browser already knows | 357 // we keep track of what accessibility objects the browser already knows |
| 354 // about. If we don't find it, then this must be the new root of the | 358 // about. If we don't find it, then this must be the new root of the |
| 355 // accessibility tree. | 359 // accessibility tree. |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 425 if (new_child_ids.find(old_child_id) == new_child_ids.end()) { | 429 if (new_child_ids.find(old_child_id) == new_child_ids.end()) { |
| 426 browser_id_map_.erase(old_child_id); | 430 browser_id_map_.erase(old_child_id); |
| 427 ClearBrowserTreeNode(old_child); | 431 ClearBrowserTreeNode(old_child); |
| 428 delete old_child; | 432 delete old_child; |
| 429 } else { | 433 } else { |
| 430 browser_child_id_map[old_child_id] = old_child; | 434 browser_child_id_map[old_child_id] = old_child; |
| 431 } | 435 } |
| 432 } | 436 } |
| 433 | 437 |
| 434 // Serialize this node. This fills in all of the fields in | 438 // Serialize this node. This fills in all of the fields in |
| 435 // AccessibilityNodeData except child_ids, which we handle below. | 439 // ui::AXNodeData except child_ids, which we handle below. |
| 436 dst->push_back(AccessibilityNodeData()); | 440 dst->push_back(ui::AXNodeData()); |
| 437 AccessibilityNodeData* serialized_node = &dst->back(); | 441 ui::AXNodeData* serialized_node = &dst->back(); |
| 438 SerializeAccessibilityNode(obj, serialized_node); | 442 SerializeAccessibilityNode(obj, serialized_node); |
| 439 if (serialized_node->id == browser_root_->id) | 443 if (serialized_node->id == browser_root_->id) |
| 440 serialized_node->role = blink::WebAXRoleRootWebArea; | 444 serialized_node->role = ui::AX_ROLE_ROOT_WEB_AREA; |
| 441 | 445 |
| 442 // Iterate over the children, make note of the ones that are new | 446 // Iterate over the children, make note of the ones that are new |
| 443 // and need to be serialized, and update the BrowserTreeNode | 447 // and need to be serialized, and update the BrowserTreeNode |
| 444 // data structure to reflect the new tree. | 448 // data structure to reflect the new tree. |
| 445 std::vector<WebAXObject> children_to_serialize; | 449 std::vector<WebAXObject> children_to_serialize; |
| 446 int child_count = obj.childCount(); | 450 int child_count = obj.childCount(); |
| 447 browser_node->children.reserve(child_count); | 451 browser_node->children.reserve(child_count); |
| 448 for (int i = 0; i < child_count; i++) { | 452 for (int i = 0; i < child_count; i++) { |
| 449 WebAXObject child = obj.childAt(i); | 453 WebAXObject child = obj.childAt(i); |
| 450 int child_id = child.axID(); | 454 int child_id = child.axID(); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 491 } | 495 } |
| 492 | 496 |
| 493 void RendererAccessibilityComplete::OnDoDefaultAction(int acc_obj_id) { | 497 void RendererAccessibilityComplete::OnDoDefaultAction(int acc_obj_id) { |
| 494 const WebDocument& document = GetMainDocument(); | 498 const WebDocument& document = GetMainDocument(); |
| 495 if (document.isNull()) | 499 if (document.isNull()) |
| 496 return; | 500 return; |
| 497 | 501 |
| 498 WebAXObject obj = document.accessibilityObjectFromID(acc_obj_id); | 502 WebAXObject obj = document.accessibilityObjectFromID(acc_obj_id); |
| 499 if (obj.isDetached()) { | 503 if (obj.isDetached()) { |
| 500 #ifndef NDEBUG | 504 #ifndef NDEBUG |
| 501 if (logging_) | 505 LOG(WARNING) << "DoDefaultAction on invalid object id " << acc_obj_id; |
| 502 LOG(WARNING) << "DoDefaultAction on invalid object id " << acc_obj_id; | |
| 503 #endif | 506 #endif |
| 504 return; | 507 return; |
| 505 } | 508 } |
| 506 | 509 |
| 507 obj.performDefaultAction(); | 510 obj.performDefaultAction(); |
| 508 } | 511 } |
| 509 | 512 |
| 510 void RendererAccessibilityComplete::OnScrollToMakeVisible( | 513 void RendererAccessibilityComplete::OnScrollToMakeVisible( |
| 511 int acc_obj_id, gfx::Rect subfocus) { | 514 int acc_obj_id, gfx::Rect subfocus) { |
| 512 const WebDocument& document = GetMainDocument(); | 515 const WebDocument& document = GetMainDocument(); |
| 513 if (document.isNull()) | 516 if (document.isNull()) |
| 514 return; | 517 return; |
| 515 | 518 |
| 516 WebAXObject obj = document.accessibilityObjectFromID(acc_obj_id); | 519 WebAXObject obj = document.accessibilityObjectFromID(acc_obj_id); |
| 517 if (obj.isDetached()) { | 520 if (obj.isDetached()) { |
| 518 #ifndef NDEBUG | 521 #ifndef NDEBUG |
| 519 if (logging_) | 522 LOG(WARNING) << "ScrollToMakeVisible on invalid object id " << acc_obj_id; |
| 520 LOG(WARNING) << "ScrollToMakeVisible on invalid object id " << acc_obj_id; | |
| 521 #endif | 523 #endif |
| 522 return; | 524 return; |
| 523 } | 525 } |
| 524 | 526 |
| 525 obj.scrollToMakeVisibleWithSubFocus( | 527 obj.scrollToMakeVisibleWithSubFocus( |
| 526 WebRect(subfocus.x(), subfocus.y(), | 528 WebRect(subfocus.x(), subfocus.y(), |
| 527 subfocus.width(), subfocus.height())); | 529 subfocus.width(), subfocus.height())); |
| 528 | 530 |
| 529 // Make sure the browser gets an event when the scroll | 531 // Make sure the browser gets an event when the scroll |
| 530 // position actually changes. | 532 // position actually changes. |
| 531 // TODO(dmazzoni): remove this once this bug is fixed: | 533 // TODO(dmazzoni): remove this once this bug is fixed: |
| 532 // https://bugs.webkit.org/show_bug.cgi?id=73460 | 534 // https://bugs.webkit.org/show_bug.cgi?id=73460 |
| 533 HandleWebAccessibilityEvent( | 535 HandleAXEvent(document.accessibilityObject(), |
| 534 document.accessibilityObject(), | 536 ui::AX_EVENT_LAYOUT_COMPLETE); |
| 535 blink::WebAXEventLayoutComplete); | |
| 536 } | 537 } |
| 537 | 538 |
| 538 void RendererAccessibilityComplete::OnScrollToPoint( | 539 void RendererAccessibilityComplete::OnScrollToPoint( |
| 539 int acc_obj_id, gfx::Point point) { | 540 int acc_obj_id, gfx::Point point) { |
| 540 const WebDocument& document = GetMainDocument(); | 541 const WebDocument& document = GetMainDocument(); |
| 541 if (document.isNull()) | 542 if (document.isNull()) |
| 542 return; | 543 return; |
| 543 | 544 |
| 544 WebAXObject obj = document.accessibilityObjectFromID(acc_obj_id); | 545 WebAXObject obj = document.accessibilityObjectFromID(acc_obj_id); |
| 545 if (obj.isDetached()) { | 546 if (obj.isDetached()) { |
| 546 #ifndef NDEBUG | 547 #ifndef NDEBUG |
| 547 if (logging_) | 548 LOG(WARNING) << "ScrollToPoint on invalid object id " << acc_obj_id; |
| 548 LOG(WARNING) << "ScrollToPoint on invalid object id " << acc_obj_id; | |
| 549 #endif | 549 #endif |
| 550 return; | 550 return; |
| 551 } | 551 } |
| 552 | 552 |
| 553 obj.scrollToGlobalPoint(WebPoint(point.x(), point.y())); | 553 obj.scrollToGlobalPoint(WebPoint(point.x(), point.y())); |
| 554 | 554 |
| 555 // Make sure the browser gets an event when the scroll | 555 // Make sure the browser gets an event when the scroll |
| 556 // position actually changes. | 556 // position actually changes. |
| 557 // TODO(dmazzoni): remove this once this bug is fixed: | 557 // TODO(dmazzoni): remove this once this bug is fixed: |
| 558 // https://bugs.webkit.org/show_bug.cgi?id=73460 | 558 // https://bugs.webkit.org/show_bug.cgi?id=73460 |
| 559 HandleWebAccessibilityEvent( | 559 HandleAXEvent(document.accessibilityObject(), |
| 560 document.accessibilityObject(), | 560 ui::AX_EVENT_LAYOUT_COMPLETE); |
| 561 blink::WebAXEventLayoutComplete); | |
| 562 } | 561 } |
| 563 | 562 |
| 564 void RendererAccessibilityComplete::OnSetTextSelection( | 563 void RendererAccessibilityComplete::OnSetTextSelection( |
| 565 int acc_obj_id, int start_offset, int end_offset) { | 564 int acc_obj_id, int start_offset, int end_offset) { |
| 566 const WebDocument& document = GetMainDocument(); | 565 const WebDocument& document = GetMainDocument(); |
| 567 if (document.isNull()) | 566 if (document.isNull()) |
| 568 return; | 567 return; |
| 569 | 568 |
| 570 WebAXObject obj = document.accessibilityObjectFromID(acc_obj_id); | 569 WebAXObject obj = document.accessibilityObjectFromID(acc_obj_id); |
| 571 if (obj.isDetached()) { | 570 if (obj.isDetached()) { |
| 572 #ifndef NDEBUG | 571 #ifndef NDEBUG |
| 573 if (logging_) | 572 LOG(WARNING) << "SetTextSelection on invalid object id " << acc_obj_id; |
| 574 LOG(WARNING) << "SetTextSelection on invalid object id " << acc_obj_id; | |
| 575 #endif | 573 #endif |
| 576 return; | 574 return; |
| 577 } | 575 } |
| 578 | 576 |
| 579 // TODO(dmazzoni): support elements other than <input>. | 577 // TODO(dmazzoni): support elements other than <input>. |
| 580 blink::WebNode node = obj.node(); | 578 blink::WebNode node = obj.node(); |
| 581 if (!node.isNull() && node.isElementNode()) { | 579 if (!node.isNull() && node.isElementNode()) { |
| 582 blink::WebElement element = node.to<blink::WebElement>(); | 580 blink::WebElement element = node.to<blink::WebElement>(); |
| 583 blink::WebInputElement* input_element = | 581 blink::WebInputElement* input_element = |
| 584 blink::toWebInputElement(&element); | 582 blink::toWebInputElement(&element); |
| 585 if (input_element && input_element->isTextField()) | 583 if (input_element && input_element->isTextField()) |
| 586 input_element->setSelectionRange(start_offset, end_offset); | 584 input_element->setSelectionRange(start_offset, end_offset); |
| 587 } | 585 } |
| 588 } | 586 } |
| 589 | 587 |
| 590 void RendererAccessibilityComplete::OnEventsAck() { | 588 void RendererAccessibilityComplete::OnEventsAck() { |
| 591 DCHECK(ack_pending_); | 589 DCHECK(ack_pending_); |
| 592 ack_pending_ = false; | 590 ack_pending_ = false; |
| 593 SendPendingAccessibilityEvents(); | 591 SendPendingAccessibilityEvents(); |
| 594 } | 592 } |
| 595 | 593 |
| 596 void RendererAccessibilityComplete::OnSetFocus(int acc_obj_id) { | 594 void RendererAccessibilityComplete::OnSetFocus(int acc_obj_id) { |
| 597 const WebDocument& document = GetMainDocument(); | 595 const WebDocument& document = GetMainDocument(); |
| 598 if (document.isNull()) | 596 if (document.isNull()) |
| 599 return; | 597 return; |
| 600 | 598 |
| 601 WebAXObject obj = document.accessibilityObjectFromID(acc_obj_id); | 599 WebAXObject obj = document.accessibilityObjectFromID(acc_obj_id); |
| 602 if (obj.isDetached()) { | 600 if (obj.isDetached()) { |
| 603 #ifndef NDEBUG | 601 #ifndef NDEBUG |
| 604 if (logging_) { | 602 LOG(WARNING) << "OnSetAccessibilityFocus on invalid object id " |
| 605 LOG(WARNING) << "OnSetAccessibilityFocus on invalid object id " | 603 << acc_obj_id; |
| 606 << acc_obj_id; | |
| 607 } | |
| 608 #endif | 604 #endif |
| 609 return; | 605 return; |
| 610 } | 606 } |
| 611 | 607 |
| 612 WebAXObject root = document.accessibilityObject(); | 608 WebAXObject root = document.accessibilityObject(); |
| 613 if (root.isDetached()) { | 609 if (root.isDetached()) { |
| 614 #ifndef NDEBUG | 610 #ifndef NDEBUG |
| 615 if (logging_) { | 611 LOG(WARNING) << "OnSetAccessibilityFocus but root is invalid"; |
| 616 LOG(WARNING) << "OnSetAccessibilityFocus but root is invalid"; | |
| 617 } | |
| 618 #endif | 612 #endif |
| 619 return; | 613 return; |
| 620 } | 614 } |
| 621 | 615 |
| 622 // By convention, calling SetFocus on the root of the tree should clear the | 616 // By convention, calling SetFocus on the root of the tree should clear the |
| 623 // current focus. Otherwise set the focus to the new node. | 617 // current focus. Otherwise set the focus to the new node. |
| 624 if (acc_obj_id == root.axID()) | 618 if (acc_obj_id == root.axID()) |
| 625 render_view()->GetWebView()->clearFocusedNode(); | 619 render_view()->GetWebView()->clearFocusedNode(); |
| 626 else | 620 else |
| 627 obj.setFocused(true); | 621 obj.setFocused(true); |
| 628 } | 622 } |
| 629 | 623 |
| 630 void RendererAccessibilityComplete::OnFatalError() { | 624 void RendererAccessibilityComplete::OnFatalError() { |
| 631 CHECK(false) << "Invalid accessibility tree."; | 625 CHECK(false) << "Invalid accessibility tree."; |
| 632 } | 626 } |
| 633 | 627 |
| 634 } // namespace content | 628 } // namespace content |
| OLD | NEW |