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

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

Issue 17045010: Revert 207875 "Native Android accessibility." (Closed) Base URL: svn://svn.chromium.org/chrome/
Patch Set: 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 | Annotate | Revision Log
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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 "content/browser/accessibility/browser_accessibility_manager_android.h" 5 #include "content/browser/accessibility/browser_accessibility_manager_android.h"
6 6
7 #include <cmath> 7 #include <cmath>
8 8
9 #include "base/android/jni_android.h" 9 #include "base/android/jni_android.h"
10 #include "base/android/jni_string.h" 10 #include "base/android/jni_string.h"
11 #include "base/strings/string_number_conversions.h" 11 #include "base/strings/string_number_conversions.h"
12 #include "base/strings/utf_string_conversions.h" 12 #include "base/strings/utf_string_conversions.h"
13 #include "base/values.h" 13 #include "base/values.h"
14 #include "content/browser/accessibility/browser_accessibility_android.h" 14 #include "content/browser/accessibility/browser_accessibility_android.h"
15 #include "content/common/accessibility_messages.h" 15 #include "content/common/accessibility_messages.h"
16 #include "jni/BrowserAccessibilityManager_jni.h"
17 16
18 using base::android::AttachCurrentThread; 17 using base::android::AttachCurrentThread;
19 using base::android::ScopedJavaLocalRef; 18 using base::android::ScopedJavaLocalRef;
20 19
21 namespace { 20 namespace {
22 21
23 // These are enums from android.view.accessibility.AccessibilityEvent in Java:
24 enum {
25 ANDROID_ACCESSIBILITY_EVENT_TYPE_VIEW_TEXT_CHANGED = 16,
26 ANDROID_ACCESSIBILITY_EVENT_TYPE_VIEW_TEXT_SELECTION_CHANGED = 8192
27 };
28
29 // Restricts |val| to the range [min, max]. 22 // Restricts |val| to the range [min, max].
30 int Clamp(int val, int min, int max) { 23 int Clamp(int val, int min, int max) {
31 return std::min(std::max(val, min), max); 24 return std::min(std::max(val, min), max);
32 } 25 }
33 26
34 } // anonymous namespace 27 } // anonymous namespace
35 28
36 namespace content { 29 namespace content {
37 30
38 namespace aria_strings { 31 namespace aria_strings {
(...skipping 12 matching lines...) Expand all
51 44
52 BrowserAccessibilityManagerAndroid::BrowserAccessibilityManagerAndroid( 45 BrowserAccessibilityManagerAndroid::BrowserAccessibilityManagerAndroid(
53 ScopedJavaLocalRef<jobject> content_view_core, 46 ScopedJavaLocalRef<jobject> content_view_core,
54 const AccessibilityNodeData& src, 47 const AccessibilityNodeData& src,
55 BrowserAccessibilityDelegate* delegate, 48 BrowserAccessibilityDelegate* delegate,
56 BrowserAccessibilityFactory* factory) 49 BrowserAccessibilityFactory* factory)
57 : BrowserAccessibilityManager(src, delegate, factory) { 50 : BrowserAccessibilityManager(src, delegate, factory) {
58 if (content_view_core.is_null()) 51 if (content_view_core.is_null())
59 return; 52 return;
60 53
61 JNIEnv* env = AttachCurrentThread(); 54 // TODO(aboxhall): set up Java references
62 java_ref_ = JavaObjectWeakGlobalRef(
63 env, Java_BrowserAccessibilityManager_create(
64 env, reinterpret_cast<jint>(this), content_view_core.obj()).obj());
65 } 55 }
66 56
67 BrowserAccessibilityManagerAndroid::~BrowserAccessibilityManagerAndroid() { 57 BrowserAccessibilityManagerAndroid::~BrowserAccessibilityManagerAndroid() {
68 JNIEnv* env = AttachCurrentThread(); 58 JNIEnv* env = base::android::AttachCurrentThread();
69 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 59 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
70 if (obj.is_null()) 60 if (obj.is_null())
71 return; 61 return;
72 62
73 Java_BrowserAccessibilityManager_onNativeObjectDestroyed(env, obj.obj()); 63 // TODO(aboxhall): tear down Java references
74 } 64 }
75 65
76 // static 66 // static
77 AccessibilityNodeData BrowserAccessibilityManagerAndroid::GetEmptyDocument() { 67 AccessibilityNodeData BrowserAccessibilityManagerAndroid::GetEmptyDocument() {
78 AccessibilityNodeData empty_document; 68 AccessibilityNodeData empty_document;
79 empty_document.id = 0; 69 empty_document.id = 0;
80 empty_document.role = AccessibilityNodeData::ROLE_ROOT_WEB_AREA; 70 empty_document.role = AccessibilityNodeData::ROLE_ROOT_WEB_AREA;
81 empty_document.state = 1 << AccessibilityNodeData::STATE_READONLY; 71 empty_document.state = 1 << AccessibilityNodeData::STATE_READONLY;
82 return empty_document; 72 return empty_document;
83 } 73 }
84 74
85 void BrowserAccessibilityManagerAndroid::NotifyAccessibilityEvent( 75 void BrowserAccessibilityManagerAndroid::NotifyAccessibilityEvent(
86 int type, 76 int type,
87 BrowserAccessibility* node) { 77 BrowserAccessibility* node) {
88 JNIEnv* env = AttachCurrentThread(); 78 JNIEnv* env = base::android::AttachCurrentThread();
89 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); 79 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
90 if (obj.is_null()) 80 if (obj.is_null())
91 return; 81 return;
92 82
93 switch (type) { 83 // TODO(aboxhall): call into appropriate Java method for each type of
94 case AccessibilityNotificationLoadComplete: 84 // notification
95 Java_BrowserAccessibilityManager_handlePageLoaded(
96 env, obj.obj(), focus_->renderer_id());
97 break;
98 case AccessibilityNotificationFocusChanged:
99 Java_BrowserAccessibilityManager_handleFocusChanged(
100 env, obj.obj(), node->renderer_id());
101 break;
102 case AccessibilityNotificationCheckStateChanged:
103 Java_BrowserAccessibilityManager_handleCheckStateChanged(
104 env, obj.obj(), node->renderer_id());
105 break;
106 case AccessibilityNotificationScrolledToAnchor:
107 Java_BrowserAccessibilityManager_handleScrolledToAnchor(
108 env, obj.obj(), node->renderer_id());
109 break;
110 case AccessibilityNotificationAlert:
111 // An alert is a special case of live region. Fall through to the
112 // next case to handle it.
113 case AccessibilityNotificationObjectShow: {
114 // This event is fired when an object appears in a live region.
115 // Speak its text.
116 BrowserAccessibilityAndroid* android_node =
117 static_cast<BrowserAccessibilityAndroid*>(node);
118 Java_BrowserAccessibilityManager_announceLiveRegionText(
119 env, obj.obj(),
120 base::android::ConvertUTF16ToJavaString(
121 env, android_node->GetText()).obj());
122 break;
123 }
124 case AccessibilityNotificationSelectedTextChanged:
125 Java_BrowserAccessibilityManager_handleTextSelectionChanged(
126 env, obj.obj(), node->renderer_id());
127 break;
128 case AccessibilityNotificationChildrenChanged:
129 case AccessibilityNotificationTextChanged:
130 case AccessibilityNotificationValueChanged:
131 if (node->IsEditableText()) {
132 Java_BrowserAccessibilityManager_handleEditableTextChanged(
133 env, obj.obj(), node->renderer_id());
134 } else {
135 Java_BrowserAccessibilityManager_handleContentChanged(
136 env, obj.obj(), node->renderer_id());
137 }
138 break;
139 default:
140 // There are some notifications that aren't meaningful on Android.
141 // It's okay to skip them.
142 break;
143 }
144 } 85 }
145 86
146 jint BrowserAccessibilityManagerAndroid::GetRootId(JNIEnv* env, jobject obj) { 87 jint BrowserAccessibilityManagerAndroid::GetRootId(JNIEnv* env, jobject obj) {
147 return static_cast<jint>(root_->renderer_id()); 88 return static_cast<jint>(root_->renderer_id());
148 } 89 }
149 90
150 jint BrowserAccessibilityManagerAndroid::HitTest( 91 jint BrowserAccessibilityManagerAndroid::HitTest(
151 JNIEnv* env, jobject obj, jint x, jint y) { 92 JNIEnv* env, jobject obj, jint x, jint y) {
152 BrowserAccessibilityAndroid* result = 93 BrowserAccessibilityAndroid* result =
153 static_cast<BrowserAccessibilityAndroid*>( 94 static_cast<BrowserAccessibilityAndroid*>(
154 root_->BrowserAccessibilityForPoint(gfx::Point(x, y))); 95 root_->BrowserAccessibilityForPoint(gfx::Point(x, y)));
155 96
156 if (!result) 97 if (!result)
157 return root_->renderer_id(); 98 return root_->renderer_id();
158 99
159 if (result->IsFocusable()) 100 if (result->IsFocusable())
160 return result->renderer_id(); 101 return result->renderer_id();
161 102
162 // Examine the children of |result| to find the nearest accessibility focus 103 // Examine the children of |result| to find the nearest accessibility focus
163 // candidate 104 // candidate
164 BrowserAccessibility* nearest_node = FuzzyHitTest(x, y, result); 105 BrowserAccessibility* nearest_node = FuzzyHitTest(x, y, result);
165 if (nearest_node) 106 if (nearest_node)
166 return nearest_node->renderer_id(); 107 return nearest_node->renderer_id();
167 108
168 return root_->renderer_id(); 109 return root_->renderer_id();
169 } 110 }
170 111
171 jboolean BrowserAccessibilityManagerAndroid::PopulateAccessibilityNodeInfo(
172 JNIEnv* env, jobject obj, jobject info, jint id) {
173 BrowserAccessibilityAndroid* node = static_cast<BrowserAccessibilityAndroid*>(
174 GetFromRendererID(id));
175 if (!node)
176 return false;
177
178 if (node->parent()) {
179 Java_BrowserAccessibilityManager_setAccessibilityNodeInfoParent(
180 env, obj, info, node->parent()->renderer_id());
181 }
182 if (!node->IsLeaf()) {
183 for (unsigned i = 0; i < node->child_count(); ++i) {
184 Java_BrowserAccessibilityManager_addAccessibilityNodeInfoChild(
185 env, obj, info, node->children()[i]->renderer_id());
186 }
187 }
188 Java_BrowserAccessibilityManager_setAccessibilityNodeInfoBooleanAttributes(
189 env, obj, info,
190 node->IsCheckable(),
191 node->IsChecked(),
192 node->IsClickable(),
193 node->IsEnabled(),
194 node->IsFocusable(),
195 node->IsFocused(),
196 node->IsPassword(),
197 node->IsScrollable(),
198 node->IsSelected(),
199 node->IsVisibleToUser());
200 Java_BrowserAccessibilityManager_setAccessibilityNodeInfoStringAttributes(
201 env, obj, info,
202 base::android::ConvertUTF8ToJavaString(env, node->GetClassName()).obj(),
203 base::android::ConvertUTF16ToJavaString(env, node->GetText()).obj());
204
205 gfx::Rect absolute_rect = node->GetLocalBoundsRect();
206 gfx::Rect parent_relative_rect = absolute_rect;
207 if (node->parent()) {
208 gfx::Rect parent_rect = node->parent()->GetLocalBoundsRect();
209 parent_relative_rect.Offset(-parent_rect.OffsetFromOrigin());
210 }
211 bool is_root = node->parent() == NULL;
212 Java_BrowserAccessibilityManager_setAccessibilityNodeInfoLocation(
213 env, obj, info,
214 absolute_rect.x(), absolute_rect.y(),
215 parent_relative_rect.x(), parent_relative_rect.y(),
216 absolute_rect.width(), absolute_rect.height(),
217 is_root);
218
219 return true;
220 }
221
222 jboolean BrowserAccessibilityManagerAndroid::PopulateAccessibilityEvent(
223 JNIEnv* env, jobject obj, jobject event, jint id, jint event_type) {
224 BrowserAccessibilityAndroid* node = static_cast<BrowserAccessibilityAndroid*>(
225 GetFromRendererID(id));
226 if (!node)
227 return false;
228
229 Java_BrowserAccessibilityManager_setAccessibilityEventBooleanAttributes(
230 env, obj, event,
231 node->IsChecked(),
232 node->IsEnabled(),
233 node->IsPassword(),
234 node->IsScrollable());
235 Java_BrowserAccessibilityManager_setAccessibilityEventClassName(
236 env, obj, event,
237 base::android::ConvertUTF8ToJavaString(env, node->GetClassName()).obj());
238 Java_BrowserAccessibilityManager_setAccessibilityEventListAttributes(
239 env, obj, event,
240 node->GetItemIndex(),
241 node->GetItemCount());
242 Java_BrowserAccessibilityManager_setAccessibilityEventScrollAttributes(
243 env, obj, event,
244 node->GetScrollX(),
245 node->GetScrollY(),
246 node->GetMaxScrollX(),
247 node->GetMaxScrollY());
248
249 switch (event_type) {
250 case ANDROID_ACCESSIBILITY_EVENT_TYPE_VIEW_TEXT_CHANGED:
251 Java_BrowserAccessibilityManager_setAccessibilityEventTextChangedAttrs(
252 env, obj, event,
253 node->GetTextChangeFromIndex(),
254 node->GetTextChangeAddedCount(),
255 node->GetTextChangeRemovedCount(),
256 base::android::ConvertUTF16ToJavaString(
257 env, node->GetTextChangeBeforeText()).obj(),
258 base::android::ConvertUTF16ToJavaString(env, node->GetText()).obj());
259 break;
260 case ANDROID_ACCESSIBILITY_EVENT_TYPE_VIEW_TEXT_SELECTION_CHANGED:
261 Java_BrowserAccessibilityManager_setAccessibilityEventSelectionAttrs(
262 env, obj, event,
263 node->GetSelectionStart(),
264 node->GetSelectionEnd(),
265 node->GetEditableTextLength(),
266 base::android::ConvertUTF16ToJavaString(env, node->GetText()).obj());
267 break;
268 default:
269 break;
270 }
271
272 return true;
273 }
274
275 void BrowserAccessibilityManagerAndroid::Click(
276 JNIEnv* env, jobject obj, jint id) {
277 BrowserAccessibility* node = GetFromRendererID(id);
278 if (node)
279 DoDefaultAction(*node);
280 }
281
282 void BrowserAccessibilityManagerAndroid::Focus(
283 JNIEnv* env, jobject obj, jint id) {
284 BrowserAccessibility* node = GetFromRendererID(id);
285 if (node)
286 SetFocus(node, true);
287 }
288
289 void BrowserAccessibilityManagerAndroid::Blur(JNIEnv* env, jobject obj) {
290 SetFocus(root_, true);
291 }
292
293 BrowserAccessibility* BrowserAccessibilityManagerAndroid::FuzzyHitTest( 112 BrowserAccessibility* BrowserAccessibilityManagerAndroid::FuzzyHitTest(
294 int x, int y, BrowserAccessibility* start_node) { 113 int x, int y, BrowserAccessibility* start_node) {
295 BrowserAccessibility* nearest_node = NULL; 114 BrowserAccessibility* nearest_node = NULL;
296 int min_distance = INT_MAX; 115 int min_distance = INT_MAX;
297 FuzzyHitTestImpl(x, y, start_node, &nearest_node, &min_distance); 116 FuzzyHitTestImpl(x, y, start_node, &nearest_node, &min_distance);
298 return nearest_node; 117 return nearest_node;
299 } 118 }
300 119
301 // static 120 // static
302 void BrowserAccessibilityManagerAndroid::FuzzyHitTestImpl( 121 void BrowserAccessibilityManagerAndroid::FuzzyHitTestImpl(
303 int x, int y, BrowserAccessibility* start_node, 122 int x, int y, BrowserAccessibility* start_node,
304 BrowserAccessibility** nearest_candidate, int* nearest_distance) { 123 BrowserAccessibility** nearest_candidate, int* nearest_distance) {
305 BrowserAccessibilityAndroid* node = 124 BrowserAccessibilityAndroid* node =
306 static_cast<BrowserAccessibilityAndroid*>(start_node); 125 static_cast<BrowserAccessibilityAndroid*>(start_node);
307 int distance = CalculateDistanceSquared(x, y, node); 126 int distance = CalculateDistanceSquared(x, y, node);
308 127
309 if (node->IsFocusable()) { 128 if (node->IsFocusable()) {
310 if (distance < *nearest_distance) { 129 if (distance < *nearest_distance) {
311 *nearest_candidate = node; 130 *nearest_candidate = node;
312 *nearest_distance = distance; 131 *nearest_distance = distance;
313 } 132 }
314 // Don't examine any more children of focusable node 133 // Don't examine any more children of focusable node
315 // TODO(aboxhall): what about focusable children? 134 // TODO(aboxhall): what about focusable children?
316 return; 135 return;
317 } 136 }
318 137
319 if (!node->GetText().empty()) { 138 if (!node->ComputeName().empty()) {
320 if (distance < *nearest_distance) { 139 if (distance < *nearest_distance) {
321 *nearest_candidate = node; 140 *nearest_candidate = node;
322 *nearest_distance = distance; 141 *nearest_distance = distance;
323 } 142 }
324 return; 143 return;
325 } 144 }
326 145
327 if (!node->IsLeaf()) { 146 if (!node->IsLeaf()) {
328 for (uint32 i = 0; i < node->child_count(); i++) { 147 for (uint32 i = 0; i < node->child_count(); i++) {
329 BrowserAccessibility* child = node->GetChild(i); 148 BrowserAccessibility* child = node->GetChild(i);
330 FuzzyHitTestImpl(x, y, child, nearest_candidate, nearest_distance); 149 FuzzyHitTestImpl(x, y, child, nearest_candidate, nearest_distance);
331 } 150 }
332 } 151 }
333 } 152 }
334 153
335 // static 154 // static
336 int BrowserAccessibilityManagerAndroid::CalculateDistanceSquared( 155 int BrowserAccessibilityManagerAndroid::CalculateDistanceSquared(
337 int x, int y, BrowserAccessibility* node) { 156 int x, int y, BrowserAccessibility* node) {
338 gfx::Rect node_bounds = node->GetLocalBoundsRect(); 157 gfx::Rect node_bounds = node->GetLocalBoundsRect();
339 int nearest_x = Clamp(x, node_bounds.x(), node_bounds.right()); 158 int nearest_x = Clamp(x, node_bounds.x(), node_bounds.right());
340 int nearest_y = Clamp(y, node_bounds.y(), node_bounds.bottom()); 159 int nearest_y = Clamp(y, node_bounds.y(), node_bounds.bottom());
341 int dx = std::abs(x - nearest_x); 160 int dx = std::abs(x - nearest_x);
342 int dy = std::abs(y - nearest_y); 161 int dy = std::abs(y - nearest_y);
343 return dx * dx + dy * dy; 162 return dx * dx + dy * dy;
344 } 163 }
345 164
165 jint BrowserAccessibilityManagerAndroid::GetNativeNodeById(
166 JNIEnv* env, jobject obj, jint id) {
167 return reinterpret_cast<jint>(GetFromRendererID(id));
168 }
169
346 void BrowserAccessibilityManagerAndroid::NotifyRootChanged() { 170 void BrowserAccessibilityManagerAndroid::NotifyRootChanged() {
347 JNIEnv* env = AttachCurrentThread(); 171 // TODO(aboxhall): non-stub implementation
348 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
349 if (obj.is_null())
350 return;
351
352 Java_BrowserAccessibilityManager_handleNavigate(env, obj.obj());
353 } 172 }
354 173
355 bool 174 bool
356 BrowserAccessibilityManagerAndroid::UseRootScrollOffsetsWhenComputingBounds() { 175 BrowserAccessibilityManagerAndroid::UseRootScrollOffsetsWhenComputingBounds() {
357 // The Java layer handles the root scroll offset. 176 // The Java layer handles the root scroll offset.
358 return false; 177 return false;
359 } 178 }
360 179
361 bool RegisterBrowserAccessibilityManager(JNIEnv* env) { 180 bool RegisterBrowserAccessibilityManager(JNIEnv* env) {
362 return RegisterNativesImpl(env); 181 // TODO(aboxhall): non-stub implementation
182 return false;
363 } 183 }
364 184
365 } // namespace content 185 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698