| 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 "base/bind.h" | 5 #include "base/bind.h" |
| 6 #include "base/command_line.h" | 6 #include "base/command_line.h" |
| 7 #include "base/message_loop.h" | 7 #include "base/message_loop.h" |
| 8 #include "content/common/accessibility_messages.h" | |
| 9 #include "content/public/common/content_switches.h" | 8 #include "content/public/common/content_switches.h" |
| 10 #include "content/renderer/render_view_impl.h" | 9 #include "content/renderer/render_view_impl.h" |
| 11 #include "content/renderer/renderer_accessibility.h" | 10 #include "content/renderer/renderer_accessibility.h" |
| 12 #include "third_party/WebKit/Source/WebKit/chromium/public/WebAccessibilityObjec
t.h" | 11 #include "third_party/WebKit/Source/WebKit/chromium/public/WebAccessibilityObjec
t.h" |
| 13 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h" | 12 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h" |
| 14 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" | 13 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" |
| 15 #include "third_party/WebKit/Source/WebKit/chromium/public/WebInputElement.h" | 14 #include "third_party/WebKit/Source/WebKit/chromium/public/WebInputElement.h" |
| 16 #include "third_party/WebKit/Source/WebKit/chromium/public/WebNode.h" | 15 #include "third_party/WebKit/Source/WebKit/chromium/public/WebNode.h" |
| 17 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" | 16 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" |
| 18 #include "webkit/glue/webaccessibility.h" | 17 #include "webkit/glue/webaccessibility.h" |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 77 case WebKit::WebAccessibilityNotificationValueChanged: | 76 case WebKit::WebAccessibilityNotificationValueChanged: |
| 78 *type = AccessibilityNotificationValueChangedD; | 77 *type = AccessibilityNotificationValueChangedD; |
| 79 break; | 78 break; |
| 80 default: | 79 default: |
| 81 NOTREACHED(); | 80 NOTREACHED(); |
| 82 return false; | 81 return false; |
| 83 } | 82 } |
| 84 return true; | 83 return true; |
| 85 } | 84 } |
| 86 | 85 |
| 87 RendererAccessibility::RendererAccessibility(RenderViewImpl* render_view) | 86 RendererAccessibility::RendererAccessibility(RenderViewImpl* render_view, |
| 87 AccessibilityMode mode) |
| 88 : content::RenderViewObserver(render_view), | 88 : content::RenderViewObserver(render_view), |
| 89 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)), | 89 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)), |
| 90 browser_root_(NULL), | 90 browser_root_(NULL), |
| 91 last_scroll_offset_(gfx::Size()), | 91 last_scroll_offset_(gfx::Size()), |
| 92 mode_(AccessibilityModeOff), |
| 92 ack_pending_(false), | 93 ack_pending_(false), |
| 93 logging_(false) { | 94 logging_(false) { |
| 94 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); | 95 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); |
| 95 if (command_line.HasSwitch(switches::kEnableAccessibility)) | |
| 96 WebAccessibilityObject::enableAccessibility(); | |
| 97 if (command_line.HasSwitch(switches::kEnableAccessibilityLogging)) | 96 if (command_line.HasSwitch(switches::kEnableAccessibilityLogging)) |
| 98 logging_ = true; | 97 logging_ = true; |
| 98 OnSetMode(mode); |
| 99 } | 99 } |
| 100 | 100 |
| 101 RendererAccessibility::~RendererAccessibility() { | 101 RendererAccessibility::~RendererAccessibility() { |
| 102 } | 102 } |
| 103 | 103 |
| 104 bool RendererAccessibility::OnMessageReceived(const IPC::Message& message) { | 104 bool RendererAccessibility::OnMessageReceived(const IPC::Message& message) { |
| 105 bool handled = true; | 105 bool handled = true; |
| 106 IPC_BEGIN_MESSAGE_MAP(RendererAccessibility, message) | 106 IPC_BEGIN_MESSAGE_MAP(RendererAccessibility, message) |
| 107 IPC_MESSAGE_HANDLER(AccessibilityMsg_Enable, OnEnable) | 107 IPC_MESSAGE_HANDLER(AccessibilityMsg_SetMode, OnSetMode) |
| 108 IPC_MESSAGE_HANDLER(AccessibilityMsg_SetFocus, OnSetFocus) | 108 IPC_MESSAGE_HANDLER(AccessibilityMsg_SetFocus, OnSetFocus) |
| 109 IPC_MESSAGE_HANDLER(AccessibilityMsg_DoDefaultAction, | 109 IPC_MESSAGE_HANDLER(AccessibilityMsg_DoDefaultAction, |
| 110 OnDoDefaultAction) | 110 OnDoDefaultAction) |
| 111 IPC_MESSAGE_HANDLER(AccessibilityMsg_Notifications_ACK, | 111 IPC_MESSAGE_HANDLER(AccessibilityMsg_Notifications_ACK, |
| 112 OnNotificationsAck) | 112 OnNotificationsAck) |
| 113 IPC_MESSAGE_HANDLER(AccessibilityMsg_ScrollToMakeVisible, | 113 IPC_MESSAGE_HANDLER(AccessibilityMsg_ScrollToMakeVisible, |
| 114 OnScrollToMakeVisible) | 114 OnScrollToMakeVisible) |
| 115 IPC_MESSAGE_HANDLER(AccessibilityMsg_ScrollToPoint, | 115 IPC_MESSAGE_HANDLER(AccessibilityMsg_ScrollToPoint, |
| 116 OnScrollToPoint) | 116 OnScrollToPoint) |
| 117 IPC_MESSAGE_HANDLER(AccessibilityMsg_SetTextSelection, | 117 IPC_MESSAGE_HANDLER(AccessibilityMsg_SetTextSelection, |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 296 } | 296 } |
| 297 } | 297 } |
| 298 if (!is_child_of_parent) { | 298 if (!is_child_of_parent) { |
| 299 obj = parent; | 299 obj = parent; |
| 300 notification.id = obj.axID(); | 300 notification.id = obj.axID(); |
| 301 includes_children = true; | 301 includes_children = true; |
| 302 } | 302 } |
| 303 } | 303 } |
| 304 | 304 |
| 305 AccessibilityHostMsg_NotificationParams notification_msg; | 305 AccessibilityHostMsg_NotificationParams notification_msg; |
| 306 BuildAccessibilityTree(obj, includes_children, ¬ification_msg.acc_tree); |
| 306 WebAccessibilityNotificationToAccessibilityNotification( | 307 WebAccessibilityNotificationToAccessibilityNotification( |
| 307 notification.type, ¬ification_msg.notification_type); | 308 notification.type, ¬ification_msg.notification_type); |
| 308 notification_msg.id = notification.id; | 309 notification_msg.id = notification.id; |
| 309 notification_msg.includes_children = includes_children; | 310 notification_msg.includes_children = includes_children; |
| 310 notification_msg.acc_tree = WebAccessibility(obj, includes_children); | |
| 311 if (obj.axID() == root_id) { | 311 if (obj.axID() == root_id) { |
| 312 DCHECK_EQ(notification_msg.acc_tree.role, | 312 DCHECK_EQ(notification_msg.acc_tree.role, |
| 313 WebAccessibility::ROLE_WEB_AREA); | 313 WebAccessibility::ROLE_WEB_AREA); |
| 314 notification_msg.acc_tree.role = WebAccessibility::ROLE_ROOT_WEB_AREA; | 314 notification_msg.acc_tree.role = WebAccessibility::ROLE_ROOT_WEB_AREA; |
| 315 } | 315 } |
| 316 notification_msgs.push_back(notification_msg); | 316 notification_msgs.push_back(notification_msg); |
| 317 | 317 |
| 318 if (includes_children) | 318 if (includes_children) |
| 319 UpdateBrowserTree(notification_msg.acc_tree); | 319 UpdateBrowserTree(notification_msg.acc_tree); |
| 320 | 320 |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 479 input_element->setSelectionRange(start_offset, end_offset); | 479 input_element->setSelectionRange(start_offset, end_offset); |
| 480 } | 480 } |
| 481 } | 481 } |
| 482 | 482 |
| 483 void RendererAccessibility::OnNotificationsAck() { | 483 void RendererAccessibility::OnNotificationsAck() { |
| 484 DCHECK(ack_pending_); | 484 DCHECK(ack_pending_); |
| 485 ack_pending_ = false; | 485 ack_pending_ = false; |
| 486 SendPendingAccessibilityNotifications(); | 486 SendPendingAccessibilityNotifications(); |
| 487 } | 487 } |
| 488 | 488 |
| 489 void RendererAccessibility::OnEnable() { | 489 void RendererAccessibility::OnSetMode(AccessibilityMode mode) { |
| 490 if (WebAccessibilityObject::accessibilityEnabled()) | 490 if (mode_ == mode) { |
| 491 return; | 491 return; |
| 492 } |
| 493 |
| 494 mode_ = mode; |
| 495 if (mode_ == AccessibilityModeOff) { |
| 496 // Note: should we have a way to turn off WebKit accessibility? |
| 497 // Right now it's a one-way switch. |
| 498 return; |
| 499 } |
| 492 | 500 |
| 493 WebAccessibilityObject::enableAccessibility(); | 501 WebAccessibilityObject::enableAccessibility(); |
| 494 | 502 |
| 495 const WebDocument& document = GetMainDocument(); | 503 const WebDocument& document = GetMainDocument(); |
| 496 if (!document.isNull()) { | 504 if (!document.isNull()) { |
| 497 // It's possible that the webview has already loaded a webpage without | 505 // It's possible that the webview has already loaded a webpage without |
| 498 // accessibility being enabled. Initialize the browser's cached | 506 // accessibility being enabled. Initialize the browser's cached |
| 499 // accessibility tree by sending it a 'load complete' notification. | 507 // accessibility tree by sending it a 'load complete' notification. |
| 500 PostAccessibilityNotification( | 508 PostAccessibilityNotification( |
| 501 document.accessibilityObject(), | 509 document.accessibilityObject(), |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 554 | 562 |
| 555 WebDocument RendererAccessibility::GetMainDocument() { | 563 WebDocument RendererAccessibility::GetMainDocument() { |
| 556 WebView* view = render_view()->GetWebView(); | 564 WebView* view = render_view()->GetWebView(); |
| 557 WebFrame* main_frame = view ? view->mainFrame() : NULL; | 565 WebFrame* main_frame = view ? view->mainFrame() : NULL; |
| 558 | 566 |
| 559 if (main_frame) | 567 if (main_frame) |
| 560 return main_frame->document(); | 568 return main_frame->document(); |
| 561 else | 569 else |
| 562 return WebDocument(); | 570 return WebDocument(); |
| 563 } | 571 } |
| 572 |
| 573 bool RendererAccessibility::IsEditableText(const WebAccessibilityObject& obj) { |
| 574 return (obj.roleValue() == WebKit::WebAccessibilityRoleTextArea || |
| 575 obj.roleValue() == WebKit::WebAccessibilityRoleTextField); |
| 576 } |
| 577 |
| 578 void RendererAccessibility::RecursiveAddEditableTextNodesToTree( |
| 579 const WebAccessibilityObject& src, |
| 580 WebAccessibility* dst) { |
| 581 if (IsEditableText(src)) { |
| 582 dst->children.push_back(WebAccessibility(src, false)); |
| 583 } else { |
| 584 int child_count = src.childCount(); |
| 585 std::set<int32> child_ids; |
| 586 for (int i = 0; i < child_count; ++i) { |
| 587 WebAccessibilityObject child = src.childAt(i); |
| 588 if (!child.isValid()) |
| 589 continue; |
| 590 RecursiveAddEditableTextNodesToTree(child, dst); |
| 591 } |
| 592 } |
| 593 } |
| 594 |
| 595 void RendererAccessibility::BuildAccessibilityTree( |
| 596 const WebAccessibilityObject& src, |
| 597 bool include_children, |
| 598 WebAccessibility* dst) { |
| 599 if (mode_ == AccessibilityModeComplete) { |
| 600 dst->Init(src, include_children); |
| 601 return; |
| 602 } |
| 603 |
| 604 // In Editable Text mode, we send a "collapsed" tree of only editable |
| 605 // text nodes as direct descendants of the root. |
| 606 CHECK_EQ(mode_, AccessibilityModeEditableTextOnly); |
| 607 if (IsEditableText(src)) { |
| 608 dst->Init(src, false); |
| 609 return; |
| 610 } |
| 611 |
| 612 // If it's not an editable text node, it must be the root, because |
| 613 // BuildAccessibilityTree will never be called on a non-root node |
| 614 // that isn't already in the browser's tree. |
| 615 CHECK_EQ(src.axID(), GetMainDocument().accessibilityObject().axID()); |
| 616 |
| 617 // Initialize the main document node, but don't add any children. |
| 618 dst->Init(src, false); |
| 619 |
| 620 // Find all editable text nodes and add them as children. |
| 621 RecursiveAddEditableTextNodesToTree(src, dst); |
| 622 } |
| OLD | NEW |