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

Side by Side Diff: content/browser/accessibility/browser_accessibility_manager_android.cc

Issue 15741009: Native Android accessibility. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address most reviewer feedback Created 7 years, 6 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
OLDNEW
(Empty)
1 // Copyright (c) 2013 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.
4
5 #include "content/browser/accessibility/browser_accessibility_manager_android.h"
6
7 #include <cmath>
8
9 #include "base/android/jni_android.h"
10 #include "base/android/jni_string.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "base/utf_string_conversions.h"
13 #include "base/values.h"
14 #include "content/browser/accessibility/browser_accessibility_android.h"
15 #include "content/common/accessibility_messages.h"
16 #include "jni/BrowserAccessibilityManager_jni.h"
17
18 using base::android::AttachCurrentThread;
19
20 namespace {
21
22 // Restricts |val| to the range [min, max].
23 int Clamp(int val, int min, int max) {
24 return std::min(std::max(val, min), max);
25 }
26
27 } // anonymous namespace
28
29 namespace content {
30
31 namespace aria_strings {
32 const char kAriaLivePolite[] = "polite";
33 const char kAriaLiveAssertive[] = "assertive";
34 }
35
36 // static
37 BrowserAccessibilityManager* BrowserAccessibilityManager::Create(
38 const AccessibilityNodeData& src,
39 BrowserAccessibilityDelegate* delegate,
40 BrowserAccessibilityFactory* factory) {
41 return new BrowserAccessibilityManagerAndroid(NULL, src, delegate, factory);
42 }
43
44 BrowserAccessibilityManagerAndroid::BrowserAccessibilityManagerAndroid(
45 ContentViewCoreImpl* content_view_core,
46 const AccessibilityNodeData& src,
47 BrowserAccessibilityDelegate* delegate,
48 BrowserAccessibilityFactory* factory)
49 : BrowserAccessibilityManager(src, delegate, factory),
50 content_view_core_(content_view_core) {
51 if (!content_view_core)
52 return;
53 JNIEnv* env = AttachCurrentThread();
54 base::android::ScopedJavaLocalRef<jobject> content_view_core_java =
55 content_view_core->GetJavaObject();
56 java_ref_.Reset(Java_BrowserAccessibilityManager_create(
57 env, reinterpret_cast<jint>(this), content_view_core_java.obj()));
58 }
59
60 BrowserAccessibilityManagerAndroid::~BrowserAccessibilityManagerAndroid() {
61 if (java_ref_.is_null())
62 return;
63 JNIEnv* env = AttachCurrentThread();
64 Java_BrowserAccessibilityManager_onNativeObjectDestroyed(
65 env, java_ref_.obj());
66 }
67
68 // static
69 AccessibilityNodeData BrowserAccessibilityManagerAndroid::GetEmptyDocument() {
70 AccessibilityNodeData empty_document;
71 empty_document.id = 0;
72 empty_document.role = AccessibilityNodeData::ROLE_ROOT_WEB_AREA;
73 empty_document.state = 1 << AccessibilityNodeData::STATE_READONLY;
74 return empty_document;
75 }
76
77 void BrowserAccessibilityManagerAndroid::NotifyAccessibilityEvent(
78 int type,
79 BrowserAccessibility* node) {
80 if (java_ref_.is_null())
81 return;
82
83 JNIEnv* env = AttachCurrentThread();
84 switch (type) {
85 case AccessibilityNotificationLoadComplete:
86 Java_BrowserAccessibilityManager_handlePageLoaded(
87 env, java_ref_.obj(), focus_->renderer_id());
88 break;
89 case AccessibilityNotificationFocusChanged:
90 Java_BrowserAccessibilityManager_handleFocusChanged(
91 env, java_ref_.obj(), node->renderer_id());
92 break;
93 case AccessibilityNotificationCheckStateChanged:
94 Java_BrowserAccessibilityManager_handleCheckStateChanged(
95 env, java_ref_.obj(), node->renderer_id());
96 break;
97 case AccessibilityNotificationScrolledToAnchor:
98 Java_BrowserAccessibilityManager_handleScrolledToAnchor(
99 env, java_ref_.obj(), node->renderer_id());
100 break;
101 case AccessibilityNotificationAlert:
102 Java_BrowserAccessibilityManager_announceObjectShow(
103 env, java_ref_.obj(), node->renderer_id(), JNI_TRUE);
104 case AccessibilityNotificationObjectShow:
105 Java_BrowserAccessibilityManager_announceObjectShow(
106 env, java_ref_.obj(), node->renderer_id(), JNI_FALSE);
107 case AccessibilityNotificationSelectedTextChanged:
108 Java_BrowserAccessibilityManager_handleTextSelectionChanged(
109 env, java_ref_.obj(), node->renderer_id());
110 break;
111 case AccessibilityNotificationChildrenChanged:
112 case AccessibilityNotificationTextChanged:
113 case AccessibilityNotificationValueChanged:
114 if (node->IsEditableText()) {
115 Java_BrowserAccessibilityManager_handleEditableTextChanged(
116 env, java_ref_.obj(), node->renderer_id());
117 } else {
118 Java_BrowserAccessibilityManager_handleContentChanged(
119 env, java_ref_.obj(), node->renderer_id());
120 }
121 break;
122 default:
123 break;
124 }
125 }
126
127 jint BrowserAccessibilityManagerAndroid::GetRootId(JNIEnv* env, jobject obj) {
128 return static_cast<jint>(root_->renderer_id());
129 }
130
131 jint BrowserAccessibilityManagerAndroid::HitTest(
132 JNIEnv* env, jobject obj, jint x, jint y) {
133 BrowserAccessibilityAndroid* result =
134 static_cast<BrowserAccessibilityAndroid*>(
135 root_->BrowserAccessibilityForPoint(gfx::Point(x, y)));
136
137 if (!result)
138 return root_->renderer_id();
139
140 if (result->IsFocusable())
141 return result->renderer_id();
142
143 // Examine the children of |result| to find the nearest accessibility focus
144 // candidate
145 BrowserAccessibility* nearest_node = FuzzyHitTest(x, y, result);
146 if (nearest_node)
147 return nearest_node->renderer_id();
148
149 return root_->renderer_id();
150 }
151
152 BrowserAccessibility* BrowserAccessibilityManagerAndroid::FuzzyHitTest(
153 int x, int y, BrowserAccessibility* start_node) {
154 BrowserAccessibility* nearest_node = NULL;
155 int min_distance = INT_MAX;
156 FuzzyHitTestImpl(x, y, start_node, &nearest_node, &min_distance);
157 return nearest_node;
158 }
159
160 // static
161 void BrowserAccessibilityManagerAndroid::FuzzyHitTestImpl(
162 int x, int y, BrowserAccessibility* start_node,
163 BrowserAccessibility** nearest_candidate, int* nearest_distance) {
164 BrowserAccessibilityAndroid* node =
165 static_cast<BrowserAccessibilityAndroid*>(start_node);
166 int distance = CalculateDistanceSquared(x, y, node);
167
168 if (node->IsFocusable()) {
169 if (distance < *nearest_distance) {
170 *nearest_candidate = node;
171 *nearest_distance = distance;
172 }
173 // Don't examine any more children of focusable node
174 // TODO(aboxhall): what about focusable children?
175 return;
176 }
177
178 if (!node->ComputeName().empty()) {
179 if (distance < *nearest_distance) {
180 *nearest_candidate = node;
181 *nearest_distance = distance;
182 }
183 return;
184 }
185
186 if (!node->IsLeaf()) {
187 for (uint32 i = 0; i < node->child_count(); i++) {
188 BrowserAccessibility* child = node->GetChild(i);
189 FuzzyHitTestImpl(x, y, child, nearest_candidate, nearest_distance);
190 }
191 }
192 }
193
194 // static
195 int BrowserAccessibilityManagerAndroid::CalculateDistanceSquared(
196 int x, int y, BrowserAccessibility* node) {
197 gfx::Rect node_bounds = node->GetLocalBoundsRect();
198 int nearest_x = Clamp(x, node_bounds.x(), node_bounds.right());
199 int nearest_y = Clamp(y, node_bounds.y(), node_bounds.bottom());
200 int dx = std::abs(x - nearest_x);
201 int dy = std::abs(y - nearest_y);
202 return dx * dx + dy * dy;
203 }
204
205 jint BrowserAccessibilityManagerAndroid::GetNativeNodeById(
206 JNIEnv* env, jobject obj, jint id) {
207 return reinterpret_cast<jint>(GetFromRendererID(id));
208 }
209
210 void BrowserAccessibilityManagerAndroid::NotifyRootChanged() {
211 JNIEnv* env = AttachCurrentThread();
212 Java_BrowserAccessibilityManager_handleNavigate(env, java_ref_.obj());
213 }
214
215 bool
216 BrowserAccessibilityManagerAndroid::UseRootScrollOffsetsWhenComputingBounds() {
217 // The Java layer handles the root scroll offset.
218 return false;
219 }
220
221 bool RegisterBrowserAccessibilityManager(JNIEnv* env) {
222 return RegisterNativesImpl(env);
223 }
224
225 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698