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 |