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

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: 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_(mode),
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;
99 } 98 }
100 99
101 RendererAccessibility::~RendererAccessibility() { 100 RendererAccessibility::~RendererAccessibility() {
102 } 101 }
103 102
104 bool RendererAccessibility::OnMessageReceived(const IPC::Message& message) { 103 bool RendererAccessibility::OnMessageReceived(const IPC::Message& message) {
105 bool handled = true; 104 bool handled = true;
106 IPC_BEGIN_MESSAGE_MAP(RendererAccessibility, message) 105 IPC_BEGIN_MESSAGE_MAP(RendererAccessibility, message)
107 IPC_MESSAGE_HANDLER(AccessibilityMsg_Enable, OnEnable) 106 IPC_MESSAGE_HANDLER(AccessibilityMsg_SetMode, OnSetMode)
108 IPC_MESSAGE_HANDLER(AccessibilityMsg_SetFocus, OnSetFocus) 107 IPC_MESSAGE_HANDLER(AccessibilityMsg_SetFocus, OnSetFocus)
109 IPC_MESSAGE_HANDLER(AccessibilityMsg_DoDefaultAction, 108 IPC_MESSAGE_HANDLER(AccessibilityMsg_DoDefaultAction,
110 OnDoDefaultAction) 109 OnDoDefaultAction)
111 IPC_MESSAGE_HANDLER(AccessibilityMsg_Notifications_ACK, 110 IPC_MESSAGE_HANDLER(AccessibilityMsg_Notifications_ACK,
112 OnNotificationsAck) 111 OnNotificationsAck)
113 IPC_MESSAGE_HANDLER(AccessibilityMsg_ScrollToMakeVisible, 112 IPC_MESSAGE_HANDLER(AccessibilityMsg_ScrollToMakeVisible,
114 OnScrollToMakeVisible) 113 OnScrollToMakeVisible)
115 IPC_MESSAGE_HANDLER(AccessibilityMsg_ScrollToPoint, 114 IPC_MESSAGE_HANDLER(AccessibilityMsg_ScrollToPoint,
116 OnScrollToPoint) 115 OnScrollToPoint)
117 IPC_MESSAGE_HANDLER(AccessibilityMsg_SetTextSelection, 116 IPC_MESSAGE_HANDLER(AccessibilityMsg_SetTextSelection,
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
296 } 295 }
297 } 296 }
298 if (!is_child_of_parent) { 297 if (!is_child_of_parent) {
299 obj = parent; 298 obj = parent;
300 notification.id = obj.axID(); 299 notification.id = obj.axID();
301 includes_children = true; 300 includes_children = true;
302 } 301 }
303 } 302 }
304 303
305 AccessibilityHostMsg_NotificationParams notification_msg; 304 AccessibilityHostMsg_NotificationParams notification_msg;
305 if (!BuildAccessibilityTree(
306 obj, includes_children, &notification_msg.acc_tree)) {
307 continue;
308 }
306 WebAccessibilityNotificationToAccessibilityNotification( 309 WebAccessibilityNotificationToAccessibilityNotification(
307 notification.type, &notification_msg.notification_type); 310 notification.type, &notification_msg.notification_type);
308 notification_msg.id = notification.id; 311 notification_msg.id = notification.id;
309 notification_msg.includes_children = includes_children; 312 notification_msg.includes_children = includes_children;
310 notification_msg.acc_tree = WebAccessibility(obj, includes_children);
311 if (obj.axID() == root_id) { 313 if (obj.axID() == root_id) {
312 DCHECK_EQ(notification_msg.acc_tree.role, 314 DCHECK_EQ(notification_msg.acc_tree.role,
313 WebAccessibility::ROLE_WEB_AREA); 315 WebAccessibility::ROLE_WEB_AREA);
314 notification_msg.acc_tree.role = WebAccessibility::ROLE_ROOT_WEB_AREA; 316 notification_msg.acc_tree.role = WebAccessibility::ROLE_ROOT_WEB_AREA;
315 } 317 }
316 notification_msgs.push_back(notification_msg); 318 notification_msgs.push_back(notification_msg);
317 319
318 if (includes_children) 320 if (includes_children)
319 UpdateBrowserTree(notification_msg.acc_tree); 321 UpdateBrowserTree(notification_msg.acc_tree);
320 322
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
479 input_element->setSelectionRange(start_offset, end_offset); 481 input_element->setSelectionRange(start_offset, end_offset);
480 } 482 }
481 } 483 }
482 484
483 void RendererAccessibility::OnNotificationsAck() { 485 void RendererAccessibility::OnNotificationsAck() {
484 DCHECK(ack_pending_); 486 DCHECK(ack_pending_);
485 ack_pending_ = false; 487 ack_pending_ = false;
486 SendPendingAccessibilityNotifications(); 488 SendPendingAccessibilityNotifications();
487 } 489 }
488 490
489 void RendererAccessibility::OnEnable() { 491 void RendererAccessibility::OnSetMode(AccessibilityMode mode) {
490 if (WebAccessibilityObject::accessibilityEnabled()) 492 if (mode_ == mode) {
491 return; 493 return;
494 }
495
496 mode_ = mode;
497 if (mode_ == AccessibilityModeOff) {
498 // Note: should we have a way to turn off WebKit accessibility?
499 // Right now it's a one-way switch.
500 return;
501 }
492 502
493 WebAccessibilityObject::enableAccessibility(); 503 WebAccessibilityObject::enableAccessibility();
494 504
495 const WebDocument& document = GetMainDocument(); 505 const WebDocument& document = GetMainDocument();
496 if (!document.isNull()) { 506 if (!document.isNull()) {
497 // It's possible that the webview has already loaded a webpage without 507 // It's possible that the webview has already loaded a webpage without
498 // accessibility being enabled. Initialize the browser's cached 508 // accessibility being enabled. Initialize the browser's cached
499 // accessibility tree by sending it a 'load complete' notification. 509 // accessibility tree by sending it a 'load complete' notification.
500 PostAccessibilityNotification( 510 PostAccessibilityNotification(
501 document.accessibilityObject(), 511 document.accessibilityObject(),
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
554 564
555 WebDocument RendererAccessibility::GetMainDocument() { 565 WebDocument RendererAccessibility::GetMainDocument() {
556 WebView* view = render_view()->GetWebView(); 566 WebView* view = render_view()->GetWebView();
557 WebFrame* main_frame = view ? view->mainFrame() : NULL; 567 WebFrame* main_frame = view ? view->mainFrame() : NULL;
558 568
559 if (main_frame) 569 if (main_frame)
560 return main_frame->document(); 570 return main_frame->document();
561 else 571 else
562 return WebDocument(); 572 return WebDocument();
563 } 573 }
574
575 bool RendererAccessibility::IsEditableText(const WebAccessibilityObject& obj) {
576 return (obj.roleValue() == WebKit::WebAccessibilityRoleTextArea ||
577 obj.roleValue() == WebKit::WebAccessibilityRoleTextField);
578 }
579
580 void RendererAccessibility::RecursiveAddEditableTextNodesToTree(
581 const WebAccessibilityObject& src,
582 WebAccessibility* dst) {
583 if (IsEditableText(src)) {
584 dst->children.push_back(WebAccessibility(src, false));
585 } else {
586 int child_count = src.childCount();
587 std::set<int32> child_ids;
588 for (int i = 0; i < child_count; ++i) {
589 WebAccessibilityObject child = src.childAt(i);
590 if (!child.isValid())
591 continue;
592 RecursiveAddEditableTextNodesToTree(child, dst);
593 }
594 }
595 }
596
597 bool RendererAccessibility::BuildAccessibilityTree(
598 const WebAccessibilityObject& src,
599 bool include_children,
600 WebAccessibility* dst) {
601 const WebDocument& document = GetMainDocument();
602 if (document.isNull())
603 return false;
604 WebAccessibilityObject root = document.accessibilityObject();
605
606 if (mode_ == AccessibilityModeComplete) {
607 dst->Init(src, include_children);
608 return true;
609 }
610
611 // 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
612 // text nodes as direct descendants of the root. If a notification is
613 // sent on any node other than the root or an editable text node, ignore it.
614 CHECK_EQ(mode_, AccessibilityModeEditableTextOnly);
615 if (IsEditableText(src)) {
616 dst->Init(src, false);
617 return true;
618 }
619
620 if (src.axID() != root.axID())
621 return false;
622
623 // Initialize the main document node, but don't add any children.
624 dst->Init(src, false);
625
626 // Find all editable text nodes and add them as children.
627 RecursiveAddEditableTextNodesToTree(src, dst);
628
629 return true;
630 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698