Chromium Code Reviews| Index: content/renderer/renderer_accessibility.cc |
| diff --git a/content/renderer/renderer_accessibility.cc b/content/renderer/renderer_accessibility.cc |
| index 7e879ef66fc334a9d6df256e94b3cf6f71faeb75..c756f09b871024c2bdf2898381e390d4fa28f9d2 100644 |
| --- a/content/renderer/renderer_accessibility.cc |
| +++ b/content/renderer/renderer_accessibility.cc |
| @@ -5,7 +5,6 @@ |
| #include "base/bind.h" |
| #include "base/command_line.h" |
| #include "base/message_loop.h" |
| -#include "content/common/accessibility_messages.h" |
| #include "content/public/common/content_switches.h" |
| #include "content/renderer/render_view_impl.h" |
| #include "content/renderer/renderer_accessibility.h" |
| @@ -84,16 +83,16 @@ bool WebAccessibilityNotificationToAccessibilityNotification( |
| return true; |
| } |
| -RendererAccessibility::RendererAccessibility(RenderViewImpl* render_view) |
| +RendererAccessibility::RendererAccessibility(RenderViewImpl* render_view, |
| + AccessibilityMode mode) |
| : content::RenderViewObserver(render_view), |
| ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)), |
| browser_root_(NULL), |
| last_scroll_offset_(gfx::Size()), |
| + mode_(mode), |
| ack_pending_(false), |
| logging_(false) { |
| const CommandLine& command_line = *CommandLine::ForCurrentProcess(); |
| - if (command_line.HasSwitch(switches::kEnableAccessibility)) |
| - WebAccessibilityObject::enableAccessibility(); |
| if (command_line.HasSwitch(switches::kEnableAccessibilityLogging)) |
| logging_ = true; |
| } |
| @@ -104,7 +103,7 @@ RendererAccessibility::~RendererAccessibility() { |
| bool RendererAccessibility::OnMessageReceived(const IPC::Message& message) { |
| bool handled = true; |
| IPC_BEGIN_MESSAGE_MAP(RendererAccessibility, message) |
| - IPC_MESSAGE_HANDLER(AccessibilityMsg_Enable, OnEnable) |
| + IPC_MESSAGE_HANDLER(AccessibilityMsg_SetMode, OnSetMode) |
| IPC_MESSAGE_HANDLER(AccessibilityMsg_SetFocus, OnSetFocus) |
| IPC_MESSAGE_HANDLER(AccessibilityMsg_DoDefaultAction, |
| OnDoDefaultAction) |
| @@ -303,11 +302,14 @@ void RendererAccessibility::SendPendingAccessibilityNotifications() { |
| } |
| AccessibilityHostMsg_NotificationParams notification_msg; |
| + if (!BuildAccessibilityTree( |
| + obj, includes_children, ¬ification_msg.acc_tree)) { |
| + continue; |
| + } |
| WebAccessibilityNotificationToAccessibilityNotification( |
| notification.type, ¬ification_msg.notification_type); |
| notification_msg.id = notification.id; |
| notification_msg.includes_children = includes_children; |
| - notification_msg.acc_tree = WebAccessibility(obj, includes_children); |
| if (obj.axID() == root_id) { |
| DCHECK_EQ(notification_msg.acc_tree.role, |
| WebAccessibility::ROLE_WEB_AREA); |
| @@ -486,9 +488,17 @@ void RendererAccessibility::OnNotificationsAck() { |
| SendPendingAccessibilityNotifications(); |
| } |
| -void RendererAccessibility::OnEnable() { |
| - if (WebAccessibilityObject::accessibilityEnabled()) |
| +void RendererAccessibility::OnSetMode(AccessibilityMode mode) { |
| + if (mode_ == mode) { |
| + return; |
| + } |
| + |
| + mode_ = mode; |
| + if (mode_ == AccessibilityModeOff) { |
| + // Note: should we have a way to turn off WebKit accessibility? |
| + // Right now it's a one-way switch. |
| return; |
| + } |
| WebAccessibilityObject::enableAccessibility(); |
| @@ -561,3 +571,60 @@ WebDocument RendererAccessibility::GetMainDocument() { |
| else |
| return WebDocument(); |
| } |
| + |
| +bool RendererAccessibility::IsEditableText(const WebAccessibilityObject& obj) { |
| + return (obj.roleValue() == WebKit::WebAccessibilityRoleTextArea || |
| + obj.roleValue() == WebKit::WebAccessibilityRoleTextField); |
| +} |
| + |
| +void RendererAccessibility::RecursiveAddEditableTextNodesToTree( |
| + const WebAccessibilityObject& src, |
| + WebAccessibility* dst) { |
| + if (IsEditableText(src)) { |
| + dst->children.push_back(WebAccessibility(src, false)); |
| + } else { |
| + int child_count = src.childCount(); |
| + std::set<int32> child_ids; |
| + for (int i = 0; i < child_count; ++i) { |
| + WebAccessibilityObject child = src.childAt(i); |
| + if (!child.isValid()) |
| + continue; |
| + RecursiveAddEditableTextNodesToTree(child, dst); |
| + } |
| + } |
| +} |
| + |
| +bool RendererAccessibility::BuildAccessibilityTree( |
| + const WebAccessibilityObject& src, |
| + bool include_children, |
| + WebAccessibility* dst) { |
| + const WebDocument& document = GetMainDocument(); |
| + if (document.isNull()) |
| + return false; |
| + WebAccessibilityObject root = document.accessibilityObject(); |
| + |
| + if (mode_ == AccessibilityModeComplete) { |
| + dst->Init(src, include_children); |
| + return true; |
| + } |
| + |
| + // In Editable Text mode, we send a "collapsed" tree of only editable |
|
David Tseng
2012/04/05 01:01:25
Ignoring notifications seems risky; what happens i
dmazzoni
2012/04/06 21:47:22
Actually it turns out I can get rid of this code p
|
| + // text nodes as direct descendants of the root. If a notification is |
| + // sent on any node other than the root or an editable text node, ignore it. |
| + CHECK_EQ(mode_, AccessibilityModeEditableTextOnly); |
| + if (IsEditableText(src)) { |
| + dst->Init(src, false); |
| + return true; |
| + } |
| + |
| + if (src.axID() != root.axID()) |
| + return false; |
| + |
| + // Initialize the main document node, but don't add any children. |
| + dst->Init(src, false); |
| + |
| + // Find all editable text nodes and add them as children. |
| + RecursiveAddEditableTextNodesToTree(src, dst); |
| + |
| + return true; |
| +} |