Chromium Code Reviews| 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_(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 Loading... | |
| 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, ¬ification_msg.acc_tree)) { | |
| 307 continue; | |
| 308 } | |
| 306 WebAccessibilityNotificationToAccessibilityNotification( | 309 WebAccessibilityNotificationToAccessibilityNotification( |
| 307 notification.type, ¬ification_msg.notification_type); | 310 notification.type, ¬ification_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 Loading... | |
| 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 Loading... | |
| 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 } | |
| OLD | NEW |