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

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

Issue 15741009: Native Android accessibility. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Now build objs from C++ code using Java helpers 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
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_android.h" 5 #include "content/browser/accessibility/browser_accessibility_android.h"
6 6
7 #include "base/android/jni_android.h"
8 #include "base/android/jni_registrar.h"
9 #include "base/android/jni_string.h"
10 #include "base/android/scoped_java_ref.h"
11 #include "base/utf_string_conversions.h" 7 #include "base/utf_string_conversions.h"
12 #include "content/browser/accessibility/browser_accessibility_manager_android.h" 8 #include "content/browser/accessibility/browser_accessibility_manager_android.h"
13 #include "content/common/accessibility_messages.h" 9 #include "content/common/accessibility_messages.h"
14 #include "content/common/accessibility_node_data.h" 10 #include "content/common/accessibility_node_data.h"
15 11
16 using base::android::ScopedJavaLocalRef;
17
18 namespace content { 12 namespace content {
19 13
20 // static 14 // static
21 BrowserAccessibility* BrowserAccessibility::Create() { 15 BrowserAccessibility* BrowserAccessibility::Create() {
22 return new BrowserAccessibilityAndroid(); 16 return new BrowserAccessibilityAndroid();
23 } 17 }
24 18
25 BrowserAccessibilityAndroid::BrowserAccessibilityAndroid() { 19 BrowserAccessibilityAndroid::BrowserAccessibilityAndroid() {
26 first_time_ = true; 20 first_time_ = true;
27 } 21 }
28 22
29 bool BrowserAccessibilityAndroid::IsNative() const { 23 bool BrowserAccessibilityAndroid::IsNative() const {
30 return true; 24 return true;
31 } 25 }
32 26
33 // 27 bool BrowserAccessibilityAndroid::IsLeaf() const {
34 // Actions, called from Java. 28 if (child_count() == 0)
35 // 29 return true;
36 30
37 void BrowserAccessibilityAndroid::FocusJNI(JNIEnv* env, jobject obj) { 31 // Iframes are always allowed to contain children.
38 manager_->SetFocus(this, true); 32 if (IsIframe() ||
33 role() == AccessibilityNodeData::ROLE_ROOT_WEB_AREA ||
34 role() == AccessibilityNodeData::ROLE_WEB_AREA) {
35 return false;
36 }
37
38 // If it has a focusable child, we definitely can't leave out children.
39 if (HasFocusableChild())
40 return false;
41
42 // Headings with text can drop their children.
43 string16 name = GetText();
44 if (role() == AccessibilityNodeData::ROLE_HEADING && !name.empty())
45 return true;
46
47 // Focusable nodes with text can drop their children.
48 if (HasState(AccessibilityNodeData::STATE_FOCUSABLE) && !name.empty())
49 return true;
50
51 // Nodes with only static text as children can drop their children.
52 if (HasOnlyStaticTextChildren())
53 return true;
54
55 return false;
39 } 56 }
40 57
41 void BrowserAccessibilityAndroid::ClickJNI(JNIEnv* env, jobject obj) { 58 bool BrowserAccessibilityAndroid::IsCheckable() const {
42 manager_->DoDefaultAction(*this);
43 }
44
45 //
46 // Const accessors, called from Java.
47 //
48
49 ScopedJavaLocalRef<jstring>
50 BrowserAccessibilityAndroid::GetNameJNI(JNIEnv* env, jobject obj) const {
51 return base::android::ConvertUTF16ToJavaString(env, ComputeName());
52 }
53
54 ScopedJavaLocalRef<jobject>
55 BrowserAccessibilityAndroid::GetAbsoluteRectJNI(
56 JNIEnv* env, jobject obj) const {
57 gfx::Rect rect = GetLocalBoundsRect();
58
59 // TODO(aboxhall): replace with non-stub implementation
60 return ScopedJavaLocalRef<jobject>(env, NULL);
61 }
62
63 ScopedJavaLocalRef<jobject>
64 BrowserAccessibilityAndroid::GetRectInParentJNI(
65 JNIEnv* env, jobject obj) const {
66 gfx::Rect rect = GetLocalBoundsRect();
67 if (parent()) {
68 gfx::Rect parent_rect = parent()->GetLocalBoundsRect();
69 rect.Offset(-parent_rect.OffsetFromOrigin());
70 }
71
72 // TODO(aboxhall): replace with non-stub implementation
73 return ScopedJavaLocalRef<jobject>(env, NULL);
74 }
75
76 jboolean
77 BrowserAccessibilityAndroid::IsFocusableJNI(JNIEnv* env, jobject obj) const {
78 return static_cast<jboolean>(IsFocusable());
79 }
80
81 jboolean
82 BrowserAccessibilityAndroid::IsEditableTextJNI(JNIEnv* env, jobject obj) const {
83 return IsEditableText();
84 }
85
86 jint BrowserAccessibilityAndroid::GetParentJNI(JNIEnv* env, jobject obj) const {
87 return static_cast<jint>(parent()->renderer_id());
88 }
89
90 jint
91 BrowserAccessibilityAndroid::GetChildCountJNI(JNIEnv* env, jobject obj) const {
92 if (IsLeaf())
93 return 0;
94 else
95 return static_cast<jint>(child_count());
96 }
97
98 jint BrowserAccessibilityAndroid::GetChildIdAtJNI(JNIEnv* env,
99 jobject obj,
100 jint child_index) const {
101 return static_cast<jint>(GetChild(child_index)->renderer_id());
102 }
103
104 jboolean
105 BrowserAccessibilityAndroid::IsCheckableJNI(JNIEnv* env, jobject obj) const {
106 bool checkable = false; 59 bool checkable = false;
107 bool is_aria_pressed_defined; 60 bool is_aria_pressed_defined;
108 bool is_mixed; 61 bool is_mixed;
109 GetAriaTristate("aria-pressed", &is_aria_pressed_defined, &is_mixed); 62 GetAriaTristate("aria-pressed", &is_aria_pressed_defined, &is_mixed);
110 if (role() == AccessibilityNodeData::ROLE_CHECKBOX || 63 if (role() == AccessibilityNodeData::ROLE_CHECKBOX ||
111 role() == AccessibilityNodeData::ROLE_RADIO_BUTTON || 64 role() == AccessibilityNodeData::ROLE_RADIO_BUTTON ||
112 is_aria_pressed_defined) { 65 is_aria_pressed_defined) {
113 checkable = true; 66 checkable = true;
114 } 67 }
115 if (HasState(AccessibilityNodeData::STATE_CHECKED)) 68 if (HasState(AccessibilityNodeData::STATE_CHECKED))
116 checkable = true; 69 checkable = true;
117 return static_cast<jboolean>(checkable); 70 return checkable;
118 } 71 }
119 72
120 jboolean 73 bool BrowserAccessibilityAndroid::IsChecked() const {
121 BrowserAccessibilityAndroid::IsCheckedJNI(JNIEnv* env, jobject obj) const { 74 return HasState(AccessibilityNodeData::STATE_CHECKED);
122 return static_cast<jboolean>(
123 HasState(AccessibilityNodeData::STATE_CHECKED));
124 } 75 }
125 76
126 base::android::ScopedJavaLocalRef<jstring> 77 bool BrowserAccessibilityAndroid::IsClickable() const {
127 BrowserAccessibilityAndroid::GetClassNameJNI(JNIEnv* env, jobject obj) const { 78 return (IsLeaf() && !GetText().empty());
79 }
80
81 bool BrowserAccessibilityAndroid::IsEnabled() const {
82 return !HasState(AccessibilityNodeData::STATE_UNAVAILABLE);
83 }
84
85 bool BrowserAccessibilityAndroid::IsFocusable() const {
86 bool focusable = HasState(AccessibilityNodeData::STATE_FOCUSABLE);
87 if (IsIframe() ||
88 role() == AccessibilityNodeData::ROLE_WEB_AREA) {
89 focusable = false;
90 }
91 return focusable;
92 }
93
94 bool BrowserAccessibilityAndroid::IsFocused() const {
95 return manager()->GetFocus(manager()->GetRoot()) == this;
96 }
97
98 bool BrowserAccessibilityAndroid::IsPassword() const {
99 return HasState(AccessibilityNodeData::STATE_PROTECTED);
100 }
101
102 bool BrowserAccessibilityAndroid::IsScrollable() const {
103 int dummy;
104 return GetIntAttribute(AccessibilityNodeData::ATTR_SCROLL_X_MAX, &dummy);
105 }
106
107 bool BrowserAccessibilityAndroid::IsSelected() const {
108 return HasState(AccessibilityNodeData::STATE_SELECTED);
109 }
110
111 bool BrowserAccessibilityAndroid::IsVisibleToUser() const {
112 return !HasState(AccessibilityNodeData::STATE_INVISIBLE);
113 }
114
115 const char* BrowserAccessibilityAndroid::GetClassName() const {
128 const char* class_name = NULL; 116 const char* class_name = NULL;
129 117
130 switch(role()) { 118 switch(role()) {
131 case AccessibilityNodeData::ROLE_EDITABLE_TEXT: 119 case AccessibilityNodeData::ROLE_EDITABLE_TEXT:
132 case AccessibilityNodeData::ROLE_SPIN_BUTTON: 120 case AccessibilityNodeData::ROLE_SPIN_BUTTON:
133 case AccessibilityNodeData::ROLE_TEXTAREA: 121 case AccessibilityNodeData::ROLE_TEXTAREA:
134 case AccessibilityNodeData::ROLE_TEXT_FIELD: 122 case AccessibilityNodeData::ROLE_TEXT_FIELD:
135 class_name = "android.widget.EditText"; 123 class_name = "android.widget.EditText";
136 break; 124 break;
137 case AccessibilityNodeData::ROLE_SLIDER: 125 case AccessibilityNodeData::ROLE_SLIDER:
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
170 break; 158 break;
171 case AccessibilityNodeData::ROLE_LIST: 159 case AccessibilityNodeData::ROLE_LIST:
172 case AccessibilityNodeData::ROLE_LISTBOX: 160 case AccessibilityNodeData::ROLE_LISTBOX:
173 class_name = "android.widget.ListView"; 161 class_name = "android.widget.ListView";
174 break; 162 break;
175 default: 163 default:
176 class_name = "android.view.View"; 164 class_name = "android.view.View";
177 break; 165 break;
178 } 166 }
179 167
180 return base::android::ConvertUTF8ToJavaString(env, class_name); 168 return class_name;
181 } 169 }
182 170
183 jboolean 171 string16 BrowserAccessibilityAndroid::GetText() const {
184 BrowserAccessibilityAndroid::IsEnabledJNI(JNIEnv* env, jobject obj) const { 172 if (IsIframe() ||
185 return static_cast<jboolean>( 173 role() == AccessibilityNodeData::ROLE_WEB_AREA) {
186 !HasState(AccessibilityNodeData::STATE_UNAVAILABLE)); 174 return string16();
175 }
176
177 string16 description;
178 GetStringAttribute(AccessibilityNodeData::ATTR_DESCRIPTION, &description);
179
180 string16 text;
181 if (!name().empty())
182 text = name();
183 else if (!description.empty())
184 text = description;
185 else if (!value().empty())
186 text = value();
187
188 if (text.empty() && HasOnlyStaticTextChildren()) {
189 for (uint32 i = 0; i < child_count(); i++) {
190 BrowserAccessibility* child = GetChild(i);
191 text += static_cast<BrowserAccessibilityAndroid*>(child)->GetText();
192 }
193 }
194
195 switch(role()) {
196 case AccessibilityNodeData::ROLE_IMAGE_MAP_LINK:
197 case AccessibilityNodeData::ROLE_LINK:
198 case AccessibilityNodeData::ROLE_WEBCORE_LINK:
199 if (!text.empty())
200 text += ASCIIToUTF16(" ");
201 text += ASCIIToUTF16("Link");
202 break;
203 case AccessibilityNodeData::ROLE_HEADING:
204 // Only append "heading" if this node already has text.
205 if (!text.empty())
206 text += ASCIIToUTF16(" Heading");
207 break;
208 }
209
210 return text;
187 } 211 }
188 212
189 jboolean 213 int BrowserAccessibilityAndroid::GetItemIndex() const {
190 BrowserAccessibilityAndroid::IsFocusedJNI(JNIEnv* env, jobject obj) const {
191 return manager()->GetFocus(manager()->GetRoot()) == this;
192 }
193
194 jboolean
195 BrowserAccessibilityAndroid::IsPasswordJNI(JNIEnv* env, jobject obj) const {
196 return static_cast<jboolean>(
197 HasState(AccessibilityNodeData::STATE_PROTECTED));
198 }
199
200 jboolean
201 BrowserAccessibilityAndroid::IsScrollableJNI(JNIEnv* env, jobject obj) const {
202 int dummy;
203 bool scrollable = GetIntAttribute(
204 AccessibilityNodeData::ATTR_SCROLL_X_MAX, &dummy);
205 return static_cast<jboolean>(scrollable);
206 }
207
208 jboolean
209 BrowserAccessibilityAndroid::IsSelectedJNI(JNIEnv* env, jobject obj) const {
210 return static_cast<jboolean>(
211 HasState(AccessibilityNodeData::STATE_SELECTED));
212 }
213
214 jboolean
215 BrowserAccessibilityAndroid::IsVisibleJNI(JNIEnv* env, jobject obj) const {
216 return static_cast<jboolean>(
217 !HasState(AccessibilityNodeData::STATE_INVISIBLE));
218 }
219
220 base::android::ScopedJavaLocalRef<jstring>
221 BrowserAccessibilityAndroid::GetAriaLiveJNI(JNIEnv* env, jobject obj) const {
222 return base::android::ConvertUTF16ToJavaString(env, GetAriaLive());
223 }
224
225 jint BrowserAccessibilityAndroid::GetItemIndexJNI(
226 JNIEnv* env, jobject obj) const {
227 int index = 0; 214 int index = 0;
228 switch(role()) { 215 switch(role()) {
229 case AccessibilityNodeData::ROLE_LIST_ITEM: 216 case AccessibilityNodeData::ROLE_LIST_ITEM:
230 case AccessibilityNodeData::ROLE_LISTBOX_OPTION: 217 case AccessibilityNodeData::ROLE_LISTBOX_OPTION:
231 index = index_in_parent(); 218 index = index_in_parent();
232 break; 219 break;
233 case AccessibilityNodeData::ROLE_SLIDER: 220 case AccessibilityNodeData::ROLE_SLIDER:
234 case AccessibilityNodeData::ROLE_PROGRESS_INDICATOR: { 221 case AccessibilityNodeData::ROLE_PROGRESS_INDICATOR: {
235 float value_for_range; 222 float value_for_range;
236 if (GetFloatAttribute( 223 if (GetFloatAttribute(
237 AccessibilityNodeData::ATTR_VALUE_FOR_RANGE, &value_for_range)) { 224 AccessibilityNodeData::ATTR_VALUE_FOR_RANGE, &value_for_range)) {
238 index = static_cast<int>(value_for_range); 225 index = static_cast<int>(value_for_range);
239 } 226 }
240 break; 227 break;
241 } 228 }
242 } 229 }
243 return static_cast<jint>(index); 230 return index;
244 } 231 }
245 232
246 jint 233 int BrowserAccessibilityAndroid::GetItemCount() const {
247 BrowserAccessibilityAndroid::GetItemCountJNI(JNIEnv* env, jobject obj) const {
248 int count = 0; 234 int count = 0;
249 switch(role()) { 235 switch(role()) {
250 case AccessibilityNodeData::ROLE_LIST: 236 case AccessibilityNodeData::ROLE_LIST:
251 case AccessibilityNodeData::ROLE_LISTBOX: 237 case AccessibilityNodeData::ROLE_LISTBOX:
252 count = child_count(); 238 count = child_count();
253 break; 239 break;
254 case AccessibilityNodeData::ROLE_SLIDER: 240 case AccessibilityNodeData::ROLE_SLIDER:
255 case AccessibilityNodeData::ROLE_PROGRESS_INDICATOR: { 241 case AccessibilityNodeData::ROLE_PROGRESS_INDICATOR: {
256 float max_value_for_range; 242 float max_value_for_range;
257 if (GetFloatAttribute(AccessibilityNodeData::ATTR_MAX_VALUE_FOR_RANGE, 243 if (GetFloatAttribute(AccessibilityNodeData::ATTR_MAX_VALUE_FOR_RANGE,
258 &max_value_for_range)) { 244 &max_value_for_range)) {
259 count = static_cast<int>(max_value_for_range); 245 count = static_cast<int>(max_value_for_range);
260 } 246 }
261 break; 247 break;
262 } 248 }
263 } 249 }
264 return static_cast<jint>(count); 250 return count;
265 } 251 }
266 252
267 jint 253 int BrowserAccessibilityAndroid::GetScrollX() const {
268 BrowserAccessibilityAndroid::GetScrollXJNI(JNIEnv* env, jobject obj) const {
269 int value = 0; 254 int value = 0;
270 GetIntAttribute(AccessibilityNodeData::ATTR_SCROLL_X, &value); 255 GetIntAttribute(AccessibilityNodeData::ATTR_SCROLL_X, &value);
271 return static_cast<jint>(value); 256 return value;
272 } 257 }
273 258
274 jint 259 int BrowserAccessibilityAndroid::GetScrollY() const {
275 BrowserAccessibilityAndroid::GetScrollYJNI(JNIEnv* env, jobject obj) const {
276 int value = 0; 260 int value = 0;
277 GetIntAttribute(AccessibilityNodeData::ATTR_SCROLL_Y, &value); 261 GetIntAttribute(AccessibilityNodeData::ATTR_SCROLL_Y, &value);
278 return static_cast<jint>(value); 262 return value;
279 } 263 }
280 264
281 jint 265 int BrowserAccessibilityAndroid::GetMaxScrollX() const {
282 BrowserAccessibilityAndroid::GetMaxScrollXJNI(JNIEnv* env, jobject obj) const {
283 int value = 0; 266 int value = 0;
284 GetIntAttribute(AccessibilityNodeData::ATTR_SCROLL_X_MAX, &value); 267 GetIntAttribute(AccessibilityNodeData::ATTR_SCROLL_X_MAX, &value);
285 return static_cast<jint>(value); 268 return value;
286 } 269 }
287 270
288 jint 271 int BrowserAccessibilityAndroid::GetMaxScrollY() const {
289 BrowserAccessibilityAndroid::GetMaxScrollYJNI(JNIEnv* env, jobject obj) const {
290 int value = 0; 272 int value = 0;
291 GetIntAttribute(AccessibilityNodeData::ATTR_SCROLL_Y_MAX, &value); 273 GetIntAttribute(AccessibilityNodeData::ATTR_SCROLL_Y_MAX, &value);
292 return static_cast<jint>(value); 274 return value;
293 } 275 }
294 276
295 jboolean 277 int BrowserAccessibilityAndroid::GetTextChangeFromIndex() const {
296 BrowserAccessibilityAndroid::GetClickableJNI(JNIEnv* env, jobject obj) const {
297 return (IsLeaf() && !ComputeName().empty());
298 }
299
300 jint BrowserAccessibilityAndroid::GetSelectionStartJNI(JNIEnv* env, jobject obj)
301 const {
302 int sel_start = 0;
303 GetIntAttribute(AccessibilityNodeData::ATTR_TEXT_SEL_START, &sel_start);
304 return sel_start;
305 }
306
307 jint BrowserAccessibilityAndroid::GetSelectionEndJNI(JNIEnv* env, jobject obj)
308 const {
309 int sel_end = 0;
310 GetIntAttribute(AccessibilityNodeData::ATTR_TEXT_SEL_END, &sel_end);
311 return sel_end;
312 }
313
314 jint BrowserAccessibilityAndroid::GetEditableTextLengthJNI(
315 JNIEnv* env, jobject obj) const {
316 return value().length();
317 }
318
319 int BrowserAccessibilityAndroid::GetTextChangeFromIndexJNI(
320 JNIEnv* env, jobject obj) const {
321 size_t index = 0; 278 size_t index = 0;
322 while (index < old_value_.length() && 279 while (index < old_value_.length() &&
323 index < new_value_.length() && 280 index < new_value_.length() &&
324 old_value_[index] == new_value_[index]) { 281 old_value_[index] == new_value_[index]) {
325 index++; 282 index++;
326 } 283 }
327 return index; 284 return index;
328 } 285 }
329 286
330 jint BrowserAccessibilityAndroid::GetTextChangeAddedCountJNI( 287 int BrowserAccessibilityAndroid::GetTextChangeAddedCount() const {
331 JNIEnv* env, jobject obj) const {
332 size_t old_len = old_value_.length(); 288 size_t old_len = old_value_.length();
333 size_t new_len = new_value_.length(); 289 size_t new_len = new_value_.length();
334 size_t left = 0; 290 size_t left = 0;
335 while (left < old_len && 291 while (left < old_len &&
336 left < new_len && 292 left < new_len &&
337 old_value_[left] == new_value_[left]) { 293 old_value_[left] == new_value_[left]) {
338 left++; 294 left++;
339 } 295 }
340 size_t right = 0; 296 size_t right = 0;
341 while (right < old_len && 297 while (right < old_len &&
342 right < new_len && 298 right < new_len &&
343 old_value_[old_len - right - 1] == new_value_[new_len - right - 1]) { 299 old_value_[old_len - right - 1] == new_value_[new_len - right - 1]) {
344 right++; 300 right++;
345 } 301 }
346 return (new_len - left - right); 302 return (new_len - left - right);
347 } 303 }
348 304
349 jint BrowserAccessibilityAndroid::GetTextChangeRemovedCountJNI( 305 int BrowserAccessibilityAndroid::GetTextChangeRemovedCount() const {
350 JNIEnv* env, jobject obj) const {
351 size_t old_len = old_value_.length(); 306 size_t old_len = old_value_.length();
352 size_t new_len = new_value_.length(); 307 size_t new_len = new_value_.length();
353 size_t left = 0; 308 size_t left = 0;
354 while (left < old_len && 309 while (left < old_len &&
355 left < new_len && 310 left < new_len &&
356 old_value_[left] == new_value_[left]) { 311 old_value_[left] == new_value_[left]) {
357 left++; 312 left++;
358 } 313 }
359 size_t right = 0; 314 size_t right = 0;
360 while (right < old_len && 315 while (right < old_len &&
361 right < new_len && 316 right < new_len &&
362 old_value_[old_len - right - 1] == new_value_[new_len - right - 1]) { 317 old_value_[old_len - right - 1] == new_value_[new_len - right - 1]) {
363 right++; 318 right++;
364 } 319 }
365 return (old_len - left - right); 320 return (old_len - left - right);
366 } 321 }
367 322
368 base::android::ScopedJavaLocalRef<jstring> 323 string16 BrowserAccessibilityAndroid::GetTextChangeBeforeText() const {
369 BrowserAccessibilityAndroid::GetTextChangeBeforeTextJNI( 324 return old_value_;
370 JNIEnv* env, jobject obj) const {
371 return base::android::ConvertUTF16ToJavaString(env, old_value_);
372 } 325 }
373 326
374 string16 BrowserAccessibilityAndroid::ComputeName() const { 327 int BrowserAccessibilityAndroid::GetSelectionStart() const {
375 if (IsIframe() || 328 int sel_start = 0;
376 role() == AccessibilityNodeData::ROLE_WEB_AREA) { 329 GetIntAttribute(AccessibilityNodeData::ATTR_TEXT_SEL_START, &sel_start);
377 return string16(); 330 return sel_start;
378 }
379
380 string16 description;
381 GetStringAttribute(AccessibilityNodeData::ATTR_DESCRIPTION,
382 &description);
383
384 string16 text;
385 if (!name().empty())
386 text = name();
387 else if (!description.empty())
388 text = description;
389 else if (!value().empty())
390 text = value();
391
392 if (text.empty() && HasOnlyStaticTextChildren()) {
393 for (uint32 i = 0; i < child_count(); i++) {
394 BrowserAccessibility* child = GetChild(i);
395 text += static_cast<BrowserAccessibilityAndroid*>(child)->ComputeName();
396 }
397 }
398
399 switch(role()) {
400 case AccessibilityNodeData::ROLE_IMAGE_MAP_LINK:
401 case AccessibilityNodeData::ROLE_LINK:
402 case AccessibilityNodeData::ROLE_WEBCORE_LINK:
403 if (!text.empty())
404 text += ASCIIToUTF16(" ");
405 text += ASCIIToUTF16("Link");
406 break;
407 case AccessibilityNodeData::ROLE_HEADING:
408 // Only append "heading" if this node already has text.
409 if (!text.empty())
410 text += ASCIIToUTF16(" Heading");
411 break;
412 }
413
414 return text;
415 } 331 }
416 332
417 string16 BrowserAccessibilityAndroid::GetAriaLive() const { 333 int BrowserAccessibilityAndroid::GetSelectionEnd() const {
418 string16 aria_live; 334 int sel_end = 0;
419 if (GetStringAttribute(AccessibilityNodeData::ATTR_CONTAINER_LIVE_STATUS, 335 GetIntAttribute(AccessibilityNodeData::ATTR_TEXT_SEL_END, &sel_end);
420 &aria_live)) { 336 return sel_end;
421 return aria_live; 337 }
422 } 338
423 return string16(); 339 int BrowserAccessibilityAndroid::GetEditableTextLength() const {
340 return value().length();
424 } 341 }
425 342
426 bool BrowserAccessibilityAndroid::HasFocusableChild() const { 343 bool BrowserAccessibilityAndroid::HasFocusableChild() const {
427 for (uint32 i = 0; i < child_count(); i++) { 344 for (uint32 i = 0; i < child_count(); i++) {
428 BrowserAccessibility* child = GetChild(i); 345 BrowserAccessibility* child = GetChild(i);
429 if (child->HasState(AccessibilityNodeData::STATE_FOCUSABLE)) 346 if (child->HasState(AccessibilityNodeData::STATE_FOCUSABLE))
430 return true; 347 return true;
431 if (static_cast<BrowserAccessibilityAndroid*>(child)->HasFocusableChild()) 348 if (static_cast<BrowserAccessibilityAndroid*>(child)->HasFocusableChild())
432 return true; 349 return true;
433 } 350 }
434 return false; 351 return false;
435 } 352 }
436 353
437 bool BrowserAccessibilityAndroid::HasOnlyStaticTextChildren() const { 354 bool BrowserAccessibilityAndroid::HasOnlyStaticTextChildren() const {
438 for (uint32 i = 0; i < child_count(); i++) { 355 for (uint32 i = 0; i < child_count(); i++) {
439 BrowserAccessibility* child = GetChild(i); 356 BrowserAccessibility* child = GetChild(i);
440 if (child->role() != AccessibilityNodeData::ROLE_STATIC_TEXT) 357 if (child->role() != AccessibilityNodeData::ROLE_STATIC_TEXT)
441 return false; 358 return false;
442 } 359 }
443 return true; 360 return true;
444 } 361 }
445 362
446 bool BrowserAccessibilityAndroid::IsIframe() const { 363 bool BrowserAccessibilityAndroid::IsIframe() const {
447 string16 html_tag; 364 string16 html_tag;
448 GetStringAttribute(AccessibilityNodeData::ATTR_HTML_TAG, &html_tag); 365 GetStringAttribute(AccessibilityNodeData::ATTR_HTML_TAG, &html_tag);
449 return html_tag == ASCIIToUTF16("iframe"); 366 return html_tag == ASCIIToUTF16("iframe");
450 } 367 }
451 368
452 bool BrowserAccessibilityAndroid::IsFocusable() const {
453 bool focusable = HasState(AccessibilityNodeData::STATE_FOCUSABLE);
454 if (IsIframe() ||
455 role() == AccessibilityNodeData::ROLE_WEB_AREA) {
456 focusable = false;
457 }
458 return focusable;
459 }
460
461 bool BrowserAccessibilityAndroid::IsLeaf() const {
462 if (child_count() == 0)
463 return true;
464
465 // Iframes are always allowed to contain children.
466 if (IsIframe() ||
467 role() == AccessibilityNodeData::ROLE_ROOT_WEB_AREA ||
468 role() == AccessibilityNodeData::ROLE_WEB_AREA) {
469 return false;
470 }
471
472 // If it has a focusable child, we definitely can't leave out children.
473 if (HasFocusableChild())
474 return false;
475
476 // Headings with text can drop their children.
477 string16 name = ComputeName();
478 if (role() == AccessibilityNodeData::ROLE_HEADING && !name.empty())
479 return true;
480
481 // Focusable nodes with text can drop their children.
482 if (HasState(AccessibilityNodeData::STATE_FOCUSABLE) && !name.empty())
483 return true;
484
485 // Nodes with only static text as children can drop their children.
486 if (HasOnlyStaticTextChildren())
487 return true;
488
489 return false;
490 }
491
492 void BrowserAccessibilityAndroid::PostInitialize() { 369 void BrowserAccessibilityAndroid::PostInitialize() {
493 BrowserAccessibility::PostInitialize(); 370 BrowserAccessibility::PostInitialize();
494 371
495 if (IsEditableText()) { 372 if (IsEditableText()) {
496 if (value_ != new_value_) { 373 if (value_ != new_value_) {
497 old_value_ = new_value_; 374 old_value_ = new_value_;
498 new_value_ = value_; 375 new_value_ = value_;
499 } 376 }
500 } 377 }
501 378
502 if (role_ == AccessibilityNodeData::ROLE_ALERT && first_time_) 379 if (role_ == AccessibilityNodeData::ROLE_ALERT && first_time_)
503 manager_->NotifyAccessibilityEvent(AccessibilityNotificationAlert, this); 380 manager_->NotifyAccessibilityEvent(AccessibilityNotificationAlert, this);
504 381
505 string16 live; 382 string16 live;
506 if (GetStringAttribute(AccessibilityNodeData::ATTR_CONTAINER_LIVE_STATUS, 383 if (GetStringAttribute(AccessibilityNodeData::ATTR_CONTAINER_LIVE_STATUS,
507 &live)) { 384 &live)) {
508 NotifyLiveRegionUpdate(live); 385 NotifyLiveRegionUpdate(live);
509 } 386 }
510 387
511 first_time_ = false; 388 first_time_ = false;
512 } 389 }
513 390
514 void BrowserAccessibilityAndroid::NotifyLiveRegionUpdate(string16& aria_live) { 391 void BrowserAccessibilityAndroid::NotifyLiveRegionUpdate(string16& aria_live) {
515 if (!EqualsASCII(aria_live, aria_strings::kAriaLivePolite) && 392 if (!EqualsASCII(aria_live, aria_strings::kAriaLivePolite) &&
516 !EqualsASCII(aria_live, aria_strings::kAriaLiveAssertive)) 393 !EqualsASCII(aria_live, aria_strings::kAriaLiveAssertive))
517 return; 394 return;
518 395
519 string16 text = ComputeName(); 396 string16 text = GetText();
520 if (cached_text_ != text) { 397 if (cached_text_ != text) {
521 if (!text.empty()) { 398 if (!text.empty()) {
522 manager_->NotifyAccessibilityEvent(AccessibilityNotificationObjectShow, 399 manager_->NotifyAccessibilityEvent(AccessibilityNotificationObjectShow,
523 this); 400 this);
524 } 401 }
525 cached_text_ = text; 402 cached_text_ = text;
526 } 403 }
527 } 404 }
528 405
529 bool RegisterBrowserAccessibility(JNIEnv* env) {
530 // TODO(aboxhall): replace with non-stub implementation
531 return false;
532 }
533
534 } // namespace content 406 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698