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