Loosen up heuristics for detecting account creation forms.
[chromium-blink-merge.git] / content / renderer / renderer_accessibility_focus_only.cc
blobd78e125038ee0518ceb682f01620159dda6bcf31
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
3 // found in the LICENSE file.
5 #include "content/renderer/renderer_accessibility_focus_only.h"
7 #include "content/common/accessibility_node_data.h"
8 #include "content/renderer/render_view_impl.h"
9 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h"
10 #include "third_party/WebKit/Source/WebKit/chromium/public/WebElement.h"
11 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
12 #include "third_party/WebKit/Source/WebKit/chromium/public/WebNode.h"
13 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
15 using WebKit::WebDocument;
16 using WebKit::WebElement;
17 using WebKit::WebFrame;
18 using WebKit::WebNode;
19 using WebKit::WebView;
21 namespace {
22 // The root node will always have id 1. Let each child node have a new
23 // id starting with 2.
24 const int kInitialId = 2;
27 namespace content {
29 RendererAccessibilityFocusOnly::RendererAccessibilityFocusOnly(
30 RenderViewImpl* render_view)
31 : RendererAccessibility(render_view),
32 next_id_(kInitialId) {
35 RendererAccessibilityFocusOnly::~RendererAccessibilityFocusOnly() {
38 void RendererAccessibilityFocusOnly::HandleWebAccessibilityNotification(
39 const WebKit::WebAccessibilityObject& obj,
40 WebKit::WebAccessibilityNotification notification) {
41 // Do nothing.
44 void RendererAccessibilityFocusOnly::FocusedNodeChanged(const WebNode& node) {
45 // Send the new accessible tree and post a native focus event.
46 HandleFocusedNodeChanged(node, true);
49 void RendererAccessibilityFocusOnly::DidFinishLoad(WebKit::WebFrame* frame) {
50 WebView* view = render_view()->GetWebView();
51 if (view->focusedFrame() != frame)
52 return;
54 WebDocument document = frame->document();
55 // Send an accessible tree to the browser, but do not post a native
56 // focus event. This is important so that if focus is initially in an
57 // editable text field, Windows will know to pop up the keyboard if the
58 // user touches it and focus doesn't change.
59 HandleFocusedNodeChanged(document.focusedNode(), false);
62 void RendererAccessibilityFocusOnly::HandleFocusedNodeChanged(
63 const WebNode& node,
64 bool send_focus_event) {
65 const WebDocument& document = GetMainDocument();
66 if (document.isNull())
67 return;
69 bool node_has_focus;
70 bool node_is_editable_text;
71 // Check HasIMETextFocus first, because it will correctly handle
72 // focus in a text box inside a ppapi plug-in. Otherwise fall back on
73 // checking the focused node in WebKit.
74 if (render_view_->HasIMETextFocus()) {
75 node_has_focus = true;
76 node_is_editable_text = true;
77 } else {
78 node_has_focus = !node.isNull();
79 node_is_editable_text =
80 node_has_focus && render_view_->IsEditableNode(node);
83 std::vector<AccessibilityHostMsg_NotificationParams> notifications;
84 notifications.push_back(AccessibilityHostMsg_NotificationParams());
85 AccessibilityHostMsg_NotificationParams& notification = notifications[0];
87 // If we want to update the browser's accessibility tree but not send a
88 // native focus changed notification, we can send a LayoutComplete
89 // notification, which doesn't post a native event on Windows.
90 notification.notification_type =
91 send_focus_event ?
92 AccessibilityNotificationFocusChanged :
93 AccessibilityNotificationLayoutComplete;
95 // This means that the new tree we send supercedes any previous tree,
96 // not just a previous node.
97 notification.includes_children = true;
99 // Set the id that the notification applies to: the root node if nothing
100 // has focus, otherwise the focused node.
101 notification.id = node_has_focus ? next_id_ : 1;
103 // Always include the root of the tree, the document. It always has id 1.
104 notification.acc_tree.id = 1;
105 notification.acc_tree.role = AccessibilityNodeData::ROLE_ROOT_WEB_AREA;
106 notification.acc_tree.state =
107 (1 << AccessibilityNodeData::STATE_READONLY) |
108 (1 << AccessibilityNodeData::STATE_FOCUSABLE);
109 if (!node_has_focus)
110 notification.acc_tree.state |= (1 << AccessibilityNodeData::STATE_FOCUSED);
111 notification.acc_tree.location = gfx::Rect(render_view_->size());
113 notification.acc_tree.children.push_back(AccessibilityNodeData());
114 AccessibilityNodeData& child = notification.acc_tree.children[0];
115 child.id = next_id_;
116 child.role = AccessibilityNodeData::ROLE_GROUP;
118 if (!node.isNull() && node.isElementNode()) {
119 child.location = gfx::Rect(
120 const_cast<WebNode&>(node).to<WebElement>().boundsInViewportSpace());
121 } else {
122 child.location = gfx::Rect();
125 if (node_has_focus) {
126 child.state =
127 (1 << AccessibilityNodeData::STATE_FOCUSABLE) |
128 (1 << AccessibilityNodeData::STATE_FOCUSED);
129 if (!node_is_editable_text)
130 child.state |= (1 << AccessibilityNodeData::STATE_READONLY);
133 #ifndef NDEBUG
134 if (logging_) {
135 LOG(INFO) << "Accessibility update: \n"
136 << "routing id=" << routing_id()
137 << " notification="
138 << AccessibilityNotificationToString(notification.notification_type)
139 << "\n" << notification.acc_tree.DebugString(true);
141 #endif
143 Send(new AccessibilityHostMsg_Notifications(routing_id(), notifications));
145 // Increment the id, wrap back when we get past a million.
146 next_id_++;
147 if (next_id_ > 1000000)
148 next_id_ = kInitialId;
151 } // namespace content