OLD | NEW |
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/i18n/break_iterator.h" | 7 #include "base/i18n/break_iterator.h" |
8 #include "base/strings/string_util.h" | 8 #include "base/strings/string_util.h" |
9 #include "base/strings/stringprintf.h" | 9 #include "base/strings/stringprintf.h" |
10 #include "base/strings/utf_string_conversions.h" | 10 #include "base/strings/utf_string_conversions.h" |
(...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
323 GetRole() == ui::AX_ROLE_WEB_AREA) { | 323 GetRole() == ui::AX_ROLE_WEB_AREA) { |
324 return base::string16(); | 324 return base::string16(); |
325 } | 325 } |
326 | 326 |
327 // See comment in browser_accessibility_win.cc for details. | 327 // See comment in browser_accessibility_win.cc for details. |
328 // The difference here is that we can only expose one accessible | 328 // The difference here is that we can only expose one accessible |
329 // name on Android, not 2 or 3 like on Windows or Mac. | 329 // name on Android, not 2 or 3 like on Windows or Mac. |
330 | 330 |
331 // First, always return the |value| attribute if this is an | 331 // First, always return the |value| attribute if this is an |
332 // input field. | 332 // input field. |
333 if (!value().empty()) { | 333 base::string16 value = GetString16Attribute(ui::AX_ATTR_VALUE); |
| 334 if (!value.empty()) { |
334 if (HasState(ui::AX_STATE_EDITABLE)) | 335 if (HasState(ui::AX_STATE_EDITABLE)) |
335 return base::UTF8ToUTF16(value()); | 336 return value; |
336 | 337 |
337 switch (GetRole()) { | 338 switch (GetRole()) { |
338 case ui::AX_ROLE_COMBO_BOX: | 339 case ui::AX_ROLE_COMBO_BOX: |
339 case ui::AX_ROLE_POP_UP_BUTTON: | 340 case ui::AX_ROLE_POP_UP_BUTTON: |
340 case ui::AX_ROLE_TEXT_AREA: | 341 case ui::AX_ROLE_TEXT_AREA: |
341 case ui::AX_ROLE_TEXT_FIELD: | 342 case ui::AX_ROLE_TEXT_FIELD: |
342 return base::UTF8ToUTF16(value()); | 343 return value; |
343 } | 344 } |
344 } | 345 } |
345 | 346 |
346 // For color wells, the color is stored in separate attributes. | 347 // For color wells, the color is stored in separate attributes. |
347 // Perhaps we could return color names in the future? | 348 // Perhaps we could return color names in the future? |
348 if (GetRole() == ui::AX_ROLE_COLOR_WELL) { | 349 if (GetRole() == ui::AX_ROLE_COLOR_WELL) { |
349 int red = GetIntAttribute(ui::AX_ATTR_COLOR_VALUE_RED); | 350 int red = GetIntAttribute(ui::AX_ATTR_COLOR_VALUE_RED); |
350 int green = GetIntAttribute(ui::AX_ATTR_COLOR_VALUE_GREEN); | 351 int green = GetIntAttribute(ui::AX_ATTR_COLOR_VALUE_GREEN); |
351 int blue = GetIntAttribute(ui::AX_ATTR_COLOR_VALUE_BLUE); | 352 int blue = GetIntAttribute(ui::AX_ATTR_COLOR_VALUE_BLUE); |
352 return base::UTF8ToUTF16( | 353 return base::UTF8ToUTF16( |
353 base::StringPrintf("#%02X%02X%02X", red, green, blue)); | 354 base::StringPrintf("#%02X%02X%02X", red, green, blue)); |
354 } | 355 } |
355 | 356 |
356 // Always prefer visible text if this is a link. Sites sometimes add | 357 // Always prefer visible text if this is a link. Sites sometimes add |
357 // a "title" attribute to a link with more information, but we can't | 358 // a "title" attribute to a link with more information, but we can't |
358 // lose the link text. | 359 // lose the link text. |
359 if (!name().empty() && GetRole() == ui::AX_ROLE_LINK) | 360 base::string16 name = GetString16Attribute(ui::AX_ATTR_NAME); |
360 return base::UTF8ToUTF16(name()); | 361 if (!name.empty() && GetRole() == ui::AX_ROLE_LINK) |
| 362 return name; |
361 | 363 |
362 // If there's no text value, the basic rule is: prefer description | 364 // If there's no text value, the basic rule is: prefer description |
363 // (aria-labelledby or aria-label), then help (title), then name | 365 // (aria-labelledby or aria-label), then help (title), then name |
364 // (inner text), then value (control value). However, if | 366 // (inner text), then value (control value). However, if |
365 // title_elem_id is set, that means there's a label element | 367 // title_elem_id is set, that means there's a label element |
366 // supplying the name and then name takes precedence over help. | 368 // supplying the name and then name takes precedence over help. |
367 // TODO(dmazzoni): clean this up by providing more granular labels in | 369 // TODO(dmazzoni): clean this up by providing more granular labels in |
368 // Blink, making the platform-specific mapping to accessible text simpler. | 370 // Blink, making the platform-specific mapping to accessible text simpler. |
369 base::string16 description = GetString16Attribute(ui::AX_ATTR_DESCRIPTION); | 371 base::string16 description = GetString16Attribute(ui::AX_ATTR_DESCRIPTION); |
370 base::string16 help = GetString16Attribute(ui::AX_ATTR_HELP); | 372 base::string16 help = GetString16Attribute(ui::AX_ATTR_HELP); |
371 | 373 |
372 base::string16 placeholder; | 374 base::string16 placeholder; |
373 switch (GetRole()) { | 375 switch (GetRole()) { |
374 case ui::AX_ROLE_DATE: | 376 case ui::AX_ROLE_DATE: |
375 case ui::AX_ROLE_TEXT_AREA: | 377 case ui::AX_ROLE_TEXT_AREA: |
376 case ui::AX_ROLE_TEXT_FIELD: | 378 case ui::AX_ROLE_TEXT_FIELD: |
377 case ui::AX_ROLE_TIME: | 379 case ui::AX_ROLE_TIME: |
378 GetHtmlAttribute("placeholder", &placeholder); | 380 GetHtmlAttribute("placeholder", &placeholder); |
379 } | 381 } |
380 | 382 |
381 int title_elem_id = GetIntAttribute( | 383 int title_elem_id = GetIntAttribute( |
382 ui::AX_ATTR_TITLE_UI_ELEMENT); | 384 ui::AX_ATTR_TITLE_UI_ELEMENT); |
383 base::string16 text; | 385 base::string16 text; |
384 if (!description.empty()) | 386 if (!description.empty()) |
385 text = description; | 387 text = description; |
386 else if (title_elem_id && !name().empty()) | 388 else if (title_elem_id && !name.empty()) |
387 text = base::UTF8ToUTF16(name()); | 389 text = name; |
388 else if (!help.empty()) | 390 else if (!help.empty()) |
389 text = help; | 391 text = help; |
390 else if (!name().empty()) | 392 else if (!name.empty()) |
391 text = base::UTF8ToUTF16(name()); | 393 text = name; |
392 else if (!placeholder.empty()) | 394 else if (!placeholder.empty()) |
393 text = placeholder; | 395 text = placeholder; |
394 else if (!value().empty()) | 396 else if (!value.empty()) |
395 text = base::UTF8ToUTF16(value()); | 397 text = value; |
396 else if (title_elem_id) { | 398 else if (title_elem_id) { |
397 BrowserAccessibility* title_elem = | 399 BrowserAccessibility* title_elem = |
398 manager()->GetFromID(title_elem_id); | 400 manager()->GetFromID(title_elem_id); |
399 if (title_elem) | 401 if (title_elem) |
400 text = static_cast<BrowserAccessibilityAndroid*>(title_elem)->GetText(); | 402 text = static_cast<BrowserAccessibilityAndroid*>(title_elem)->GetText(); |
401 } | 403 } |
402 | 404 |
403 // This is called from PlatformIsLeaf, so don't call PlatformChildCount | 405 // This is called from PlatformIsLeaf, so don't call PlatformChildCount |
404 // from within this! | 406 // from within this! |
405 if (text.empty() && | 407 if (text.empty() && |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
556 return sel_start; | 558 return sel_start; |
557 } | 559 } |
558 | 560 |
559 int BrowserAccessibilityAndroid::GetSelectionEnd() const { | 561 int BrowserAccessibilityAndroid::GetSelectionEnd() const { |
560 int sel_end = 0; | 562 int sel_end = 0; |
561 GetIntAttribute(ui::AX_ATTR_TEXT_SEL_END, &sel_end); | 563 GetIntAttribute(ui::AX_ATTR_TEXT_SEL_END, &sel_end); |
562 return sel_end; | 564 return sel_end; |
563 } | 565 } |
564 | 566 |
565 int BrowserAccessibilityAndroid::GetEditableTextLength() const { | 567 int BrowserAccessibilityAndroid::GetEditableTextLength() const { |
566 return value().length(); | 568 base::string16 value = GetString16Attribute(ui::AX_ATTR_VALUE); |
| 569 return value.length(); |
567 } | 570 } |
568 | 571 |
569 int BrowserAccessibilityAndroid::AndroidInputType() const { | 572 int BrowserAccessibilityAndroid::AndroidInputType() const { |
570 std::string html_tag = GetStringAttribute( | 573 std::string html_tag = GetStringAttribute( |
571 ui::AX_ATTR_HTML_TAG); | 574 ui::AX_ATTR_HTML_TAG); |
572 if (html_tag != "input") | 575 if (html_tag != "input") |
573 return ANDROID_TEXT_INPUTTYPE_TYPE_NULL; | 576 return ANDROID_TEXT_INPUTTYPE_TYPE_NULL; |
574 | 577 |
575 std::string type; | 578 std::string type; |
576 if (!GetHtmlAttribute("type", &type)) | 579 if (!GetHtmlAttribute("type", &type)) |
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
824 bool BrowserAccessibilityAndroid::IsIframe() const { | 827 bool BrowserAccessibilityAndroid::IsIframe() const { |
825 base::string16 html_tag = GetString16Attribute( | 828 base::string16 html_tag = GetString16Attribute( |
826 ui::AX_ATTR_HTML_TAG); | 829 ui::AX_ATTR_HTML_TAG); |
827 return html_tag == base::ASCIIToUTF16("iframe"); | 830 return html_tag == base::ASCIIToUTF16("iframe"); |
828 } | 831 } |
829 | 832 |
830 void BrowserAccessibilityAndroid::OnDataChanged() { | 833 void BrowserAccessibilityAndroid::OnDataChanged() { |
831 BrowserAccessibility::OnDataChanged(); | 834 BrowserAccessibility::OnDataChanged(); |
832 | 835 |
833 if (IsEditableText()) { | 836 if (IsEditableText()) { |
834 if (base::UTF8ToUTF16(value()) != new_value_) { | 837 base::string16 value = GetString16Attribute(ui::AX_ATTR_VALUE); |
| 838 if (value != new_value_) { |
835 old_value_ = new_value_; | 839 old_value_ = new_value_; |
836 new_value_ = base::UTF8ToUTF16(value()); | 840 new_value_ = value; |
837 } | 841 } |
838 } | 842 } |
839 | 843 |
840 if (GetRole() == ui::AX_ROLE_ALERT && first_time_) | 844 if (GetRole() == ui::AX_ROLE_ALERT && first_time_) |
841 manager()->NotifyAccessibilityEvent(ui::AX_EVENT_ALERT, this); | 845 manager()->NotifyAccessibilityEvent(ui::AX_EVENT_ALERT, this); |
842 | 846 |
843 base::string16 live; | 847 base::string16 live; |
844 if (GetString16Attribute( | 848 if (GetString16Attribute( |
845 ui::AX_ATTR_CONTAINER_LIVE_STATUS, &live)) { | 849 ui::AX_ATTR_CONTAINER_LIVE_STATUS, &live)) { |
846 NotifyLiveRegionUpdate(live); | 850 NotifyLiveRegionUpdate(live); |
(...skipping 21 matching lines...) Expand all Loading... |
868 int BrowserAccessibilityAndroid::CountChildrenWithRole(ui::AXRole role) const { | 872 int BrowserAccessibilityAndroid::CountChildrenWithRole(ui::AXRole role) const { |
869 int count = 0; | 873 int count = 0; |
870 for (uint32 i = 0; i < PlatformChildCount(); i++) { | 874 for (uint32 i = 0; i < PlatformChildCount(); i++) { |
871 if (PlatformGetChild(i)->GetRole() == role) | 875 if (PlatformGetChild(i)->GetRole() == role) |
872 count++; | 876 count++; |
873 } | 877 } |
874 return count; | 878 return count; |
875 } | 879 } |
876 | 880 |
877 } // namespace content | 881 } // namespace content |
OLD | NEW |