Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(298)

Side by Side Diff: content/renderer/renderer_accessibility.cc

Issue 9939011: Add an accessibility mode for editable text fields only. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Addressed comments and rebased. Created 8 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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, &notification_msg.acc_tree);
306 WebAccessibilityNotificationToAccessibilityNotification( 307 WebAccessibilityNotificationToAccessibilityNotification(
307 notification.type, &notification_msg.notification_type); 308 notification.type, &notification_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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698