| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2012, Google Inc. All rights reserved. | 2 * Copyright (C) 2012, Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
| 6 * are met: | 6 * are met: |
| 7 * | 7 * |
| 8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright |
| (...skipping 20 matching lines...) Expand all Loading... |
| 31 | 31 |
| 32 #include "core/accessibility/AXObjectCache.h" | 32 #include "core/accessibility/AXObjectCache.h" |
| 33 #include "core/dom/NodeTraversal.h" | 33 #include "core/dom/NodeTraversal.h" |
| 34 #include "core/dom/Text.h" | 34 #include "core/dom/Text.h" |
| 35 #include "core/html/HTMLFieldSetElement.h" | 35 #include "core/html/HTMLFieldSetElement.h" |
| 36 #include "core/html/HTMLFrameElementBase.h" | 36 #include "core/html/HTMLFrameElementBase.h" |
| 37 #include "core/html/HTMLInputElement.h" | 37 #include "core/html/HTMLInputElement.h" |
| 38 #include "core/html/HTMLLabelElement.h" | 38 #include "core/html/HTMLLabelElement.h" |
| 39 #include "core/html/HTMLLegendElement.h" | 39 #include "core/html/HTMLLegendElement.h" |
| 40 #include "core/html/HTMLSelectElement.h" | 40 #include "core/html/HTMLSelectElement.h" |
| 41 #include "core/html/HTMLTextAreaElement.h" |
| 41 #include "core/rendering/RenderObject.h" | 42 #include "core/rendering/RenderObject.h" |
| 42 #include "platform/UserGestureIndicator.h" | 43 #include "platform/UserGestureIndicator.h" |
| 43 #include "wtf/text/StringBuilder.h" | 44 #include "wtf/text/StringBuilder.h" |
| 44 | 45 |
| 45 using namespace std; | 46 using namespace std; |
| 46 | 47 |
| 47 namespace WebCore { | 48 namespace WebCore { |
| 48 | 49 |
| 49 using namespace HTMLNames; | 50 using namespace HTMLNames; |
| 50 | 51 |
| (...skipping 18 matching lines...) Expand all Loading... |
| 69 ASSERT(isDetached()); | 70 ASSERT(isDetached()); |
| 70 } | 71 } |
| 71 | 72 |
| 72 // This function implements the ARIA accessible name as described by the Mozilla | 73 // This function implements the ARIA accessible name as described by the Mozilla |
| 73 // ARIA Implementer's Guide. | 74 // ARIA Implementer's Guide. |
| 74 static String accessibleNameForNode(Node* node) | 75 static String accessibleNameForNode(Node* node) |
| 75 { | 76 { |
| 76 if (node->isTextNode()) | 77 if (node->isTextNode()) |
| 77 return toText(node)->data(); | 78 return toText(node)->data(); |
| 78 | 79 |
| 79 if (node->hasTagName(inputTag)) | 80 if (isHTMLInputElement(*node)) |
| 80 return toHTMLInputElement(node)->value(); | 81 return toHTMLInputElement(*node).value(); |
| 81 | 82 |
| 82 if (node->isHTMLElement()) { | 83 if (node->isHTMLElement()) { |
| 83 const AtomicString& alt = toHTMLElement(node)->getAttribute(altAttr); | 84 const AtomicString& alt = toHTMLElement(node)->getAttribute(altAttr); |
| 84 if (!alt.isEmpty()) | 85 if (!alt.isEmpty()) |
| 85 return alt; | 86 return alt; |
| 86 } | 87 } |
| 87 | 88 |
| 88 return String(); | 89 return String(); |
| 89 } | 90 } |
| 90 | 91 |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 179 AccessibilityRole ariaRole = ariaRoleAttribute(); | 180 AccessibilityRole ariaRole = ariaRoleAttribute(); |
| 180 if (ariaRole != UnknownRole) | 181 if (ariaRole != UnknownRole) |
| 181 return ariaRole; | 182 return ariaRole; |
| 182 | 183 |
| 183 if (node()->isLink()) | 184 if (node()->isLink()) |
| 184 return LinkRole; | 185 return LinkRole; |
| 185 if (node()->isTextNode()) | 186 if (node()->isTextNode()) |
| 186 return StaticTextRole; | 187 return StaticTextRole; |
| 187 if (node()->hasTagName(buttonTag)) | 188 if (node()->hasTagName(buttonTag)) |
| 188 return buttonRoleType(); | 189 return buttonRoleType(); |
| 189 if (node()->hasTagName(inputTag)) { | 190 if (isHTMLInputElement(*node())) { |
| 190 HTMLInputElement* input = toHTMLInputElement(node()); | 191 HTMLInputElement& input = toHTMLInputElement(*node()); |
| 191 if (input->isCheckbox()) | 192 if (input.isCheckbox()) |
| 192 return CheckBoxRole; | 193 return CheckBoxRole; |
| 193 if (input->isRadioButton()) | 194 if (input.isRadioButton()) |
| 194 return RadioButtonRole; | 195 return RadioButtonRole; |
| 195 if (input->isTextButton()) | 196 if (input.isTextButton()) |
| 196 return buttonRoleType(); | 197 return buttonRoleType(); |
| 197 if (input->isRangeControl()) | 198 if (input.isRangeControl()) |
| 198 return SliderRole; | 199 return SliderRole; |
| 199 | 200 |
| 200 const AtomicString& type = input->getAttribute(typeAttr); | 201 const AtomicString& type = input.getAttribute(typeAttr); |
| 201 if (equalIgnoringCase(type, "color")) | 202 if (equalIgnoringCase(type, "color")) |
| 202 return ColorWellRole; | 203 return ColorWellRole; |
| 203 | 204 |
| 204 return TextFieldRole; | 205 return TextFieldRole; |
| 205 } | 206 } |
| 206 if (node()->hasTagName(selectTag)) { | 207 if (isHTMLSelectElement(*node())) { |
| 207 HTMLSelectElement* selectElement = toHTMLSelectElement(node()); | 208 HTMLSelectElement& selectElement = toHTMLSelectElement(*node()); |
| 208 return selectElement->multiple() ? ListBoxRole : PopUpButtonRole; | 209 return selectElement.multiple() ? ListBoxRole : PopUpButtonRole; |
| 209 } | 210 } |
| 210 if (node()->hasTagName(textareaTag)) | 211 if (isHTMLTextAreaElement(*node())) |
| 211 return TextAreaRole; | 212 return TextAreaRole; |
| 212 if (headingLevel()) | 213 if (headingLevel()) |
| 213 return HeadingRole; | 214 return HeadingRole; |
| 214 if (node()->hasTagName(divTag)) | 215 if (node()->hasTagName(divTag)) |
| 215 return DivRole; | 216 return DivRole; |
| 216 if (node()->hasTagName(pTag)) | 217 if (node()->hasTagName(pTag)) |
| 217 return ParagraphRole; | 218 return ParagraphRole; |
| 218 if (node()->hasTagName(labelTag)) | 219 if (node()->hasTagName(labelTag)) |
| 219 return LabelRole; | 220 return LabelRole; |
| 220 if (node()->isElementNode() && toElement(node())->isFocusable()) | 221 if (node()->isElementNode() && toElement(node())->isFocusable()) |
| (...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 499 } | 500 } |
| 500 | 501 |
| 501 bool AXNodeObject::isImageButton() const | 502 bool AXNodeObject::isImageButton() const |
| 502 { | 503 { |
| 503 return isNativeImage() && isButton(); | 504 return isNativeImage() && isButton(); |
| 504 } | 505 } |
| 505 | 506 |
| 506 bool AXNodeObject::isInputImage() const | 507 bool AXNodeObject::isInputImage() const |
| 507 { | 508 { |
| 508 Node* node = this->node(); | 509 Node* node = this->node(); |
| 509 if (!node) | 510 if (roleValue() == ButtonRole && isHTMLInputElement(node)) |
| 510 return false; | 511 return toHTMLInputElement(*node).isImageButton(); |
| 511 | |
| 512 if (roleValue() == ButtonRole && node->hasTagName(inputTag)) | |
| 513 return toHTMLInputElement(node)->isImageButton(); | |
| 514 | 512 |
| 515 return false; | 513 return false; |
| 516 } | 514 } |
| 517 | 515 |
| 518 bool AXNodeObject::isLink() const | 516 bool AXNodeObject::isLink() const |
| 519 { | 517 { |
| 520 return roleValue() == LinkRole; | 518 return roleValue() == LinkRole; |
| 521 } | 519 } |
| 522 | 520 |
| 523 bool AXNodeObject::isMenu() const | 521 bool AXNodeObject::isMenu() const |
| 524 { | 522 { |
| 525 return roleValue() == MenuRole; | 523 return roleValue() == MenuRole; |
| 526 } | 524 } |
| 527 | 525 |
| 528 bool AXNodeObject::isMenuButton() const | 526 bool AXNodeObject::isMenuButton() const |
| 529 { | 527 { |
| 530 return roleValue() == MenuButtonRole; | 528 return roleValue() == MenuButtonRole; |
| 531 } | 529 } |
| 532 | 530 |
| 533 bool AXNodeObject::isMultiSelectable() const | 531 bool AXNodeObject::isMultiSelectable() const |
| 534 { | 532 { |
| 535 const AtomicString& ariaMultiSelectable = getAttribute(aria_multiselectableA
ttr); | 533 const AtomicString& ariaMultiSelectable = getAttribute(aria_multiselectableA
ttr); |
| 536 if (equalIgnoringCase(ariaMultiSelectable, "true")) | 534 if (equalIgnoringCase(ariaMultiSelectable, "true")) |
| 537 return true; | 535 return true; |
| 538 if (equalIgnoringCase(ariaMultiSelectable, "false")) | 536 if (equalIgnoringCase(ariaMultiSelectable, "false")) |
| 539 return false; | 537 return false; |
| 540 | 538 |
| 541 return node() && node()->hasTagName(selectTag) && toHTMLSelectElement(node()
)->multiple(); | 539 return isHTMLSelectElement(node()) && toHTMLSelectElement(*node()).multiple(
); |
| 542 } | 540 } |
| 543 | 541 |
| 544 bool AXNodeObject::isNativeCheckboxOrRadio() const | 542 bool AXNodeObject::isNativeCheckboxOrRadio() const |
| 545 { | 543 { |
| 546 Node* node = this->node(); | 544 Node* node = this->node(); |
| 547 if (!node || !node->hasTagName(inputTag)) | 545 if (!isHTMLInputElement(node)) |
| 548 return false; | 546 return false; |
| 549 | 547 |
| 550 HTMLInputElement* input = toHTMLInputElement(node); | 548 HTMLInputElement* input = toHTMLInputElement(node); |
| 551 return input->isCheckbox() || input->isRadioButton(); | 549 return input->isCheckbox() || input->isRadioButton(); |
| 552 } | 550 } |
| 553 | 551 |
| 554 bool AXNodeObject::isNativeImage() const | 552 bool AXNodeObject::isNativeImage() const |
| 555 { | 553 { |
| 556 Node* node = this->node(); | 554 Node* node = this->node(); |
| 557 if (!node) | 555 if (!node) |
| 558 return false; | 556 return false; |
| 559 | 557 |
| 560 if (node->hasTagName(imgTag)) | 558 if (node->hasTagName(imgTag)) |
| 561 return true; | 559 return true; |
| 562 | 560 |
| 563 if (node->hasTagName(appletTag) || node->hasTagName(embedTag) || node->hasTa
gName(objectTag)) | 561 if (node->hasTagName(appletTag) || node->hasTagName(embedTag) || node->hasTa
gName(objectTag)) |
| 564 return true; | 562 return true; |
| 565 | 563 |
| 566 if (node->hasTagName(inputTag)) | 564 if (isHTMLInputElement(*node)) |
| 567 return toHTMLInputElement(node)->isImageButton(); | 565 return toHTMLInputElement(*node).isImageButton(); |
| 568 | 566 |
| 569 return false; | 567 return false; |
| 570 } | 568 } |
| 571 | 569 |
| 572 bool AXNodeObject::isNativeTextControl() const | 570 bool AXNodeObject::isNativeTextControl() const |
| 573 { | 571 { |
| 574 Node* node = this->node(); | 572 Node* node = this->node(); |
| 575 if (!node) | 573 if (!node) |
| 576 return false; | 574 return false; |
| 577 | 575 |
| 578 if (node->hasTagName(textareaTag)) | 576 if (isHTMLTextAreaElement(*node)) |
| 579 return true; | 577 return true; |
| 580 | 578 |
| 581 if (node->hasTagName(inputTag)) { | 579 if (isHTMLInputElement(*node)) { |
| 582 HTMLInputElement* input = toHTMLInputElement(node); | 580 HTMLInputElement* input = toHTMLInputElement(node); |
| 583 return input->isText() || input->isNumberField(); | 581 return input->isText() || input->isNumberField(); |
| 584 } | 582 } |
| 585 | 583 |
| 586 return false; | 584 return false; |
| 587 } | 585 } |
| 588 | 586 |
| 589 bool AXNodeObject::isNonNativeTextControl() const | 587 bool AXNodeObject::isNonNativeTextControl() const |
| 590 { | 588 { |
| 591 if (isNativeTextControl()) | 589 if (isNativeTextControl()) |
| 592 return false; | 590 return false; |
| 593 | 591 |
| 594 if (hasContentEditableAttributeSet()) | 592 if (hasContentEditableAttributeSet()) |
| 595 return true; | 593 return true; |
| 596 | 594 |
| 597 if (isARIATextControl()) | 595 if (isARIATextControl()) |
| 598 return true; | 596 return true; |
| 599 | 597 |
| 600 return false; | 598 return false; |
| 601 } | 599 } |
| 602 | 600 |
| 603 bool AXNodeObject::isPasswordField() const | 601 bool AXNodeObject::isPasswordField() const |
| 604 { | 602 { |
| 605 Node* node = this->node(); | 603 Node* node = this->node(); |
| 606 if (!node || !node->hasTagName(inputTag)) | 604 if (!isHTMLInputElement(node)) |
| 607 return false; | 605 return false; |
| 608 | 606 |
| 609 if (ariaRoleAttribute() != UnknownRole) | 607 if (ariaRoleAttribute() != UnknownRole) |
| 610 return false; | 608 return false; |
| 611 | 609 |
| 612 return toHTMLInputElement(node)->isPasswordField(); | 610 return toHTMLInputElement(node)->isPasswordField(); |
| 613 } | 611 } |
| 614 | 612 |
| 615 bool AXNodeObject::isProgressIndicator() const | 613 bool AXNodeObject::isProgressIndicator() const |
| 616 { | 614 { |
| 617 return roleValue() == ProgressIndicatorRole; | 615 return roleValue() == ProgressIndicatorRole; |
| 618 } | 616 } |
| 619 | 617 |
| 620 bool AXNodeObject::isSlider() const | 618 bool AXNodeObject::isSlider() const |
| 621 { | 619 { |
| 622 return roleValue() == SliderRole; | 620 return roleValue() == SliderRole; |
| 623 } | 621 } |
| 624 | 622 |
| 625 bool AXNodeObject::isChecked() const | 623 bool AXNodeObject::isChecked() const |
| 626 { | 624 { |
| 627 Node* node = this->node(); | 625 Node* node = this->node(); |
| 628 if (!node) | 626 if (!node) |
| 629 return false; | 627 return false; |
| 630 | 628 |
| 631 // First test for native checkedness semantics | 629 // First test for native checkedness semantics |
| 632 if (node->hasTagName(inputTag)) | 630 if (isHTMLInputElement(*node)) |
| 633 return toHTMLInputElement(node)->shouldAppearChecked(); | 631 return toHTMLInputElement(*node).shouldAppearChecked(); |
| 634 | 632 |
| 635 // Else, if this is an ARIA checkbox or radio, respect the aria-checked attr
ibute | 633 // Else, if this is an ARIA checkbox or radio, respect the aria-checked attr
ibute |
| 636 AccessibilityRole ariaRole = ariaRoleAttribute(); | 634 AccessibilityRole ariaRole = ariaRoleAttribute(); |
| 637 if (ariaRole == RadioButtonRole || ariaRole == CheckBoxRole) { | 635 if (ariaRole == RadioButtonRole || ariaRole == CheckBoxRole) { |
| 638 if (equalIgnoringCase(getAttribute(aria_checkedAttr), "true")) | 636 if (equalIgnoringCase(getAttribute(aria_checkedAttr), "true")) |
| 639 return true; | 637 return true; |
| 640 return false; | 638 return false; |
| 641 } | 639 } |
| 642 | 640 |
| 643 // Otherwise it's not checked | 641 // Otherwise it's not checked |
| (...skipping 22 matching lines...) Expand all Loading... |
| 666 Node* node = this->node(); | 664 Node* node = this->node(); |
| 667 if (!node || !node->isElementNode()) | 665 if (!node || !node->isElementNode()) |
| 668 return true; | 666 return true; |
| 669 | 667 |
| 670 return !toElement(node)->isDisabledFormControl(); | 668 return !toElement(node)->isDisabledFormControl(); |
| 671 } | 669 } |
| 672 | 670 |
| 673 bool AXNodeObject::isIndeterminate() const | 671 bool AXNodeObject::isIndeterminate() const |
| 674 { | 672 { |
| 675 Node* node = this->node(); | 673 Node* node = this->node(); |
| 676 if (!node || !node->hasTagName(inputTag)) | 674 if (!isHTMLInputElement(node)) |
| 677 return false; | 675 return false; |
| 678 | 676 |
| 679 return toHTMLInputElement(node)->shouldAppearIndeterminate(); | 677 return toHTMLInputElement(node)->shouldAppearIndeterminate(); |
| 680 } | 678 } |
| 681 | 679 |
| 682 bool AXNodeObject::isPressed() const | 680 bool AXNodeObject::isPressed() const |
| 683 { | 681 { |
| 684 if (!isButton()) | 682 if (!isButton()) |
| 685 return false; | 683 return false; |
| 686 | 684 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 697 | 695 |
| 698 return node->active(); | 696 return node->active(); |
| 699 } | 697 } |
| 700 | 698 |
| 701 bool AXNodeObject::isReadOnly() const | 699 bool AXNodeObject::isReadOnly() const |
| 702 { | 700 { |
| 703 Node* node = this->node(); | 701 Node* node = this->node(); |
| 704 if (!node) | 702 if (!node) |
| 705 return true; | 703 return true; |
| 706 | 704 |
| 707 if (node->hasTagName(textareaTag)) | 705 if (isHTMLTextAreaElement(*node)) |
| 708 return toHTMLFormControlElement(node)->isReadOnly(); | 706 return toHTMLTextAreaElement(*node).isReadOnly(); |
| 709 | 707 |
| 710 if (node->hasTagName(inputTag)) { | 708 if (isHTMLInputElement(*node)) { |
| 711 HTMLInputElement* input = toHTMLInputElement(node); | 709 HTMLInputElement& input = toHTMLInputElement(*node); |
| 712 if (input->isTextField()) | 710 if (input.isTextField()) |
| 713 return input->isReadOnly(); | 711 return input.isReadOnly(); |
| 714 } | 712 } |
| 715 | 713 |
| 716 return !node->rendererIsEditable(); | 714 return !node->rendererIsEditable(); |
| 717 } | 715 } |
| 718 | 716 |
| 719 bool AXNodeObject::isRequired() const | 717 bool AXNodeObject::isRequired() const |
| 720 { | 718 { |
| 721 if (equalIgnoringCase(getAttribute(aria_requiredAttr), "true")) | 719 if (equalIgnoringCase(getAttribute(aria_requiredAttr), "true")) |
| 722 return true; | 720 return true; |
| 723 | 721 |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 874 if (ariaRoleAttribute() == StaticTextRole) | 872 if (ariaRoleAttribute() == StaticTextRole) |
| 875 return ariaAccessibilityDescription(); | 873 return ariaAccessibilityDescription(); |
| 876 | 874 |
| 877 if (!isTextControl()) | 875 if (!isTextControl()) |
| 878 return String(); | 876 return String(); |
| 879 | 877 |
| 880 Node* node = this->node(); | 878 Node* node = this->node(); |
| 881 if (!node) | 879 if (!node) |
| 882 return String(); | 880 return String(); |
| 883 | 881 |
| 884 if (isNativeTextControl() && (node->hasTagName(textareaTag) || node->hasTagN
ame(inputTag))) | 882 if (isNativeTextControl() && (isHTMLTextAreaElement(*node) || isHTMLInputEle
ment(*node))) |
| 885 return toHTMLTextFormControlElement(node)->value(); | 883 return toHTMLTextFormControlElement(*node).value(); |
| 886 | 884 |
| 887 if (!node->isElementNode()) | 885 if (!node->isElementNode()) |
| 888 return String(); | 886 return String(); |
| 889 | 887 |
| 890 return toElement(node)->innerText(); | 888 return toElement(node)->innerText(); |
| 891 } | 889 } |
| 892 | 890 |
| 893 AXObject* AXNodeObject::titleUIElement() const | 891 AXObject* AXNodeObject::titleUIElement() const |
| 894 { | 892 { |
| 895 if (!node() || !node()->isElementNode()) | 893 if (!node() || !node()->isElementNode()) |
| (...skipping 19 matching lines...) Expand all Loading... |
| 915 | 913 |
| 916 void AXNodeObject::colorValue(int& r, int& g, int& b) const | 914 void AXNodeObject::colorValue(int& r, int& g, int& b) const |
| 917 { | 915 { |
| 918 r = 0; | 916 r = 0; |
| 919 g = 0; | 917 g = 0; |
| 920 b = 0; | 918 b = 0; |
| 921 | 919 |
| 922 if (!isColorWell()) | 920 if (!isColorWell()) |
| 923 return; | 921 return; |
| 924 | 922 |
| 925 if (!node() || !node()->hasTagName(inputTag)) | 923 if (!isHTMLInputElement(node())) |
| 926 return; | 924 return; |
| 927 | 925 |
| 928 HTMLInputElement* input = toHTMLInputElement(node()); | 926 HTMLInputElement* input = toHTMLInputElement(node()); |
| 929 const AtomicString& type = input->getAttribute(typeAttr); | 927 const AtomicString& type = input->getAttribute(typeAttr); |
| 930 if (!equalIgnoringCase(type, "color")) | 928 if (!equalIgnoringCase(type, "color")) |
| 931 return; | 929 return; |
| 932 | 930 |
| 933 // HTMLInputElement::value always returns a string parseable by Color. | 931 // HTMLInputElement::value always returns a string parseable by Color. |
| 934 Color color; | 932 Color color; |
| 935 bool success = color.setFromString(input->value()); | 933 bool success = color.setFromString(input->value()); |
| 936 ASSERT_UNUSED(success, success); | 934 ASSERT_UNUSED(success, success); |
| 937 r = color.red(); | 935 r = color.red(); |
| 938 g = color.green(); | 936 g = color.green(); |
| 939 b = color.blue(); | 937 b = color.blue(); |
| 940 } | 938 } |
| 941 | 939 |
| 942 String AXNodeObject::valueDescription() const | 940 String AXNodeObject::valueDescription() const |
| 943 { | 941 { |
| 944 if (!supportsRangeValue()) | 942 if (!supportsRangeValue()) |
| 945 return String(); | 943 return String(); |
| 946 | 944 |
| 947 return getAttribute(aria_valuetextAttr).string(); | 945 return getAttribute(aria_valuetextAttr).string(); |
| 948 } | 946 } |
| 949 | 947 |
| 950 float AXNodeObject::valueForRange() const | 948 float AXNodeObject::valueForRange() const |
| 951 { | 949 { |
| 952 if (hasAttribute(aria_valuenowAttr)) | 950 if (hasAttribute(aria_valuenowAttr)) |
| 953 return getAttribute(aria_valuenowAttr).toFloat(); | 951 return getAttribute(aria_valuenowAttr).toFloat(); |
| 954 | 952 |
| 955 if (node() && node()->hasTagName(inputTag)) { | 953 if (isHTMLInputElement(node())) { |
| 956 HTMLInputElement* input = toHTMLInputElement(node()); | 954 HTMLInputElement& input = toHTMLInputElement(*node()); |
| 957 if (input->isRangeControl()) | 955 if (input.isRangeControl()) |
| 958 return input->valueAsNumber(); | 956 return input.valueAsNumber(); |
| 959 } | 957 } |
| 960 | 958 |
| 961 return 0.0; | 959 return 0.0; |
| 962 } | 960 } |
| 963 | 961 |
| 964 float AXNodeObject::maxValueForRange() const | 962 float AXNodeObject::maxValueForRange() const |
| 965 { | 963 { |
| 966 if (hasAttribute(aria_valuemaxAttr)) | 964 if (hasAttribute(aria_valuemaxAttr)) |
| 967 return getAttribute(aria_valuemaxAttr).toFloat(); | 965 return getAttribute(aria_valuemaxAttr).toFloat(); |
| 968 | 966 |
| 969 if (node() && node()->hasTagName(inputTag)) { | 967 if (isHTMLInputElement(node())) { |
| 970 HTMLInputElement* input = toHTMLInputElement(node()); | 968 HTMLInputElement& input = toHTMLInputElement(*node()); |
| 971 if (input->isRangeControl()) | 969 if (input.isRangeControl()) |
| 972 return input->maximum(); | 970 return input.maximum(); |
| 973 } | 971 } |
| 974 | 972 |
| 975 return 0.0; | 973 return 0.0; |
| 976 } | 974 } |
| 977 | 975 |
| 978 float AXNodeObject::minValueForRange() const | 976 float AXNodeObject::minValueForRange() const |
| 979 { | 977 { |
| 980 if (hasAttribute(aria_valueminAttr)) | 978 if (hasAttribute(aria_valueminAttr)) |
| 981 return getAttribute(aria_valueminAttr).toFloat(); | 979 return getAttribute(aria_valueminAttr).toFloat(); |
| 982 | 980 |
| 983 if (node() && node()->hasTagName(inputTag)) { | 981 if (isHTMLInputElement(node())) { |
| 984 HTMLInputElement* input = toHTMLInputElement(node()); | 982 HTMLInputElement& input = toHTMLInputElement(*node()); |
| 985 if (input->isRangeControl()) | 983 if (input.isRangeControl()) |
| 986 return input->minimum(); | 984 return input.minimum(); |
| 987 } | 985 } |
| 988 | 986 |
| 989 return 0.0; | 987 return 0.0; |
| 990 } | 988 } |
| 991 | 989 |
| 992 float AXNodeObject::stepValueForRange() const | 990 float AXNodeObject::stepValueForRange() const |
| 993 { | 991 { |
| 994 return getAttribute(stepAttr).toFloat(); | 992 return getAttribute(stepAttr).toFloat(); |
| 995 } | 993 } |
| 996 | 994 |
| 997 String AXNodeObject::stringValue() const | 995 String AXNodeObject::stringValue() const |
| 998 { | 996 { |
| 999 Node* node = this->node(); | 997 Node* node = this->node(); |
| 1000 if (!node) | 998 if (!node) |
| 1001 return String(); | 999 return String(); |
| 1002 | 1000 |
| 1003 if (ariaRoleAttribute() == StaticTextRole) { | 1001 if (ariaRoleAttribute() == StaticTextRole) { |
| 1004 String staticText = text(); | 1002 String staticText = text(); |
| 1005 if (!staticText.length()) | 1003 if (!staticText.length()) |
| 1006 staticText = textUnderElement(); | 1004 staticText = textUnderElement(); |
| 1007 return staticText; | 1005 return staticText; |
| 1008 } | 1006 } |
| 1009 | 1007 |
| 1010 if (node->isTextNode()) | 1008 if (node->isTextNode()) |
| 1011 return textUnderElement(); | 1009 return textUnderElement(); |
| 1012 | 1010 |
| 1013 if (node->hasTagName(selectTag)) { | 1011 if (isHTMLSelectElement(*node)) { |
| 1014 HTMLSelectElement* selectElement = toHTMLSelectElement(node); | 1012 HTMLSelectElement& selectElement = toHTMLSelectElement(*node); |
| 1015 int selectedIndex = selectElement->selectedIndex(); | 1013 int selectedIndex = selectElement.selectedIndex(); |
| 1016 const Vector<HTMLElement*> listItems = selectElement->listItems(); | 1014 const Vector<HTMLElement*> listItems = selectElement.listItems(); |
| 1017 if (selectedIndex >= 0 && static_cast<size_t>(selectedIndex) < listItems
.size()) { | 1015 if (selectedIndex >= 0 && static_cast<size_t>(selectedIndex) < listItems
.size()) { |
| 1018 const AtomicString& overriddenDescription = listItems[selectedIndex]
->fastGetAttribute(aria_labelAttr); | 1016 const AtomicString& overriddenDescription = listItems[selectedIndex]
->fastGetAttribute(aria_labelAttr); |
| 1019 if (!overriddenDescription.isNull()) | 1017 if (!overriddenDescription.isNull()) |
| 1020 return overriddenDescription; | 1018 return overriddenDescription; |
| 1021 } | 1019 } |
| 1022 if (!selectElement->multiple()) | 1020 if (!selectElement.multiple()) |
| 1023 return selectElement->value(); | 1021 return selectElement.value(); |
| 1024 return String(); | 1022 return String(); |
| 1025 } | 1023 } |
| 1026 | 1024 |
| 1027 if (isTextControl()) | 1025 if (isTextControl()) |
| 1028 return text(); | 1026 return text(); |
| 1029 | 1027 |
| 1030 // FIXME: We might need to implement a value here for more types | 1028 // FIXME: We might need to implement a value here for more types |
| 1031 // FIXME: It would be better not to advertise a value at all for the types f
or which we don't implement one; | 1029 // FIXME: It would be better not to advertise a value at all for the types f
or which we don't implement one; |
| 1032 // this would require subclassing or making accessibilityAttributeNames do s
omething other than return a | 1030 // this would require subclassing or making accessibilityAttributeNames do s
omething other than return a |
| 1033 // single static array. | 1031 // single static array. |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1157 | 1155 |
| 1158 return String(); | 1156 return String(); |
| 1159 } | 1157 } |
| 1160 | 1158 |
| 1161 String AXNodeObject::title() const | 1159 String AXNodeObject::title() const |
| 1162 { | 1160 { |
| 1163 Node* node = this->node(); | 1161 Node* node = this->node(); |
| 1164 if (!node) | 1162 if (!node) |
| 1165 return String(); | 1163 return String(); |
| 1166 | 1164 |
| 1167 bool isInputTag = node->hasTagName(inputTag); | 1165 bool isInputElement = isHTMLInputElement(*node); |
| 1168 if (isInputTag) { | 1166 if (isInputElement) { |
| 1169 HTMLInputElement* input = toHTMLInputElement(node); | 1167 HTMLInputElement& input = toHTMLInputElement(*node); |
| 1170 if (input->isTextButton()) | 1168 if (input.isTextButton()) |
| 1171 return input->valueWithDefault(); | 1169 return input.valueWithDefault(); |
| 1172 } | 1170 } |
| 1173 | 1171 |
| 1174 if (isInputTag || AXObject::isARIAInput(ariaRoleAttribute()) || isControl())
{ | 1172 if (isInputElement || AXObject::isARIAInput(ariaRoleAttribute()) || isContro
l()) { |
| 1175 HTMLLabelElement* label = labelForElement(toElement(node)); | 1173 HTMLLabelElement* label = labelForElement(toElement(node)); |
| 1176 if (label && !exposesTitleUIElement()) | 1174 if (label && !exposesTitleUIElement()) |
| 1177 return label->innerText(); | 1175 return label->innerText(); |
| 1178 } | 1176 } |
| 1179 | 1177 |
| 1180 // If this node isn't rendered, there's no inner text we can extract from a
select element. | 1178 // If this node isn't rendered, there's no inner text we can extract from a
select element. |
| 1181 if (!isAXRenderObject() && node->hasTagName(selectTag)) | 1179 if (!isAXRenderObject() && isHTMLSelectElement(*node)) |
| 1182 return String(); | 1180 return String(); |
| 1183 | 1181 |
| 1184 switch (roleValue()) { | 1182 switch (roleValue()) { |
| 1185 case PopUpButtonRole: | 1183 case PopUpButtonRole: |
| 1186 // Native popup buttons should not use their button children's text as a
title. That value is retrieved through stringValue(). | 1184 // Native popup buttons should not use their button children's text as a
title. That value is retrieved through stringValue(). |
| 1187 if (node->hasTagName(selectTag)) | 1185 if (isHTMLSelectElement(*node)) |
| 1188 return String(); | 1186 return String(); |
| 1189 case ButtonRole: | 1187 case ButtonRole: |
| 1190 case ToggleButtonRole: | 1188 case ToggleButtonRole: |
| 1191 case CheckBoxRole: | 1189 case CheckBoxRole: |
| 1192 case ListBoxOptionRole: | 1190 case ListBoxOptionRole: |
| 1193 case MenuButtonRole: | 1191 case MenuButtonRole: |
| 1194 case MenuItemRole: | 1192 case MenuItemRole: |
| 1195 case RadioButtonRole: | 1193 case RadioButtonRole: |
| 1196 case TabRole: | 1194 case TabRole: |
| 1197 return textUnderElement(); | 1195 return textUnderElement(); |
| (...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1391 return true; | 1389 return true; |
| 1392 } | 1390 } |
| 1393 } | 1391 } |
| 1394 | 1392 |
| 1395 Element* AXNodeObject::actionElement() const | 1393 Element* AXNodeObject::actionElement() const |
| 1396 { | 1394 { |
| 1397 Node* node = this->node(); | 1395 Node* node = this->node(); |
| 1398 if (!node) | 1396 if (!node) |
| 1399 return 0; | 1397 return 0; |
| 1400 | 1398 |
| 1401 if (node->hasTagName(inputTag)) { | 1399 if (isHTMLInputElement(*node)) { |
| 1402 HTMLInputElement* input = toHTMLInputElement(node); | 1400 HTMLInputElement& input = toHTMLInputElement(*node); |
| 1403 if (!input->isDisabledFormControl() && (isCheckboxOrRadio() || input->is
TextButton())) | 1401 if (!input.isDisabledFormControl() && (isCheckboxOrRadio() || input.isTe
xtButton())) |
| 1404 return input; | 1402 return &input; |
| 1405 } else if (node->hasTagName(buttonTag)) { | 1403 } else if (node->hasTagName(buttonTag)) { |
| 1406 return toElement(node); | 1404 return toElement(node); |
| 1407 } | 1405 } |
| 1408 | 1406 |
| 1409 if (isFileUploadButton()) | 1407 if (isFileUploadButton()) |
| 1410 return toElement(node); | 1408 return toElement(node); |
| 1411 | 1409 |
| 1412 if (AXObject::isARIAInput(ariaRoleAttribute())) | 1410 if (AXObject::isARIAInput(ariaRoleAttribute())) |
| 1413 return toElement(node); | 1411 return toElement(node); |
| 1414 | 1412 |
| (...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1757 if (titleUIElement) | 1755 if (titleUIElement) |
| 1758 textOrder.append(AccessibilityText(String(), LabelByElementText, titleUI
Element)); | 1756 textOrder.append(AccessibilityText(String(), LabelByElementText, titleUI
Element)); |
| 1759 } | 1757 } |
| 1760 | 1758 |
| 1761 void AXNodeObject::visibleText(Vector<AccessibilityText>& textOrder) const | 1759 void AXNodeObject::visibleText(Vector<AccessibilityText>& textOrder) const |
| 1762 { | 1760 { |
| 1763 Node* node = this->node(); | 1761 Node* node = this->node(); |
| 1764 if (!node) | 1762 if (!node) |
| 1765 return; | 1763 return; |
| 1766 | 1764 |
| 1767 bool isInputTag = node->hasTagName(inputTag); | 1765 if (isHTMLInputElement(*node)) { |
| 1768 if (isInputTag) { | 1766 HTMLInputElement& input = toHTMLInputElement(*node); |
| 1769 HTMLInputElement* input = toHTMLInputElement(node); | 1767 if (input.isTextButton()) { |
| 1770 if (input->isTextButton()) { | 1768 textOrder.append(AccessibilityText(input.valueWithDefault(), Visible
Text)); |
| 1771 textOrder.append(AccessibilityText(input->valueWithDefault(), Visibl
eText)); | |
| 1772 return; | 1769 return; |
| 1773 } | 1770 } |
| 1774 } | 1771 } |
| 1775 | 1772 |
| 1776 // If this node isn't rendered, there's no inner text we can extract from a
select element. | 1773 // If this node isn't rendered, there's no inner text we can extract from a
select element. |
| 1777 if (!isAXRenderObject() && node->hasTagName(selectTag)) | 1774 if (!isAXRenderObject() && node->hasTagName(selectTag)) |
| 1778 return; | 1775 return; |
| 1779 | 1776 |
| 1780 bool useTextUnderElement = false; | 1777 bool useTextUnderElement = false; |
| 1781 | 1778 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1804 useTextUnderElement = true; | 1801 useTextUnderElement = true; |
| 1805 | 1802 |
| 1806 if (useTextUnderElement) { | 1803 if (useTextUnderElement) { |
| 1807 String text = textUnderElement(); | 1804 String text = textUnderElement(); |
| 1808 if (!text.isEmpty()) | 1805 if (!text.isEmpty()) |
| 1809 textOrder.append(AccessibilityText(text, ChildrenText)); | 1806 textOrder.append(AccessibilityText(text, ChildrenText)); |
| 1810 } | 1807 } |
| 1811 } | 1808 } |
| 1812 | 1809 |
| 1813 } // namespace WebCore | 1810 } // namespace WebCore |
| OLD | NEW |