| OLD | NEW | 
|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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 | 5 | 
| 6 #include "modules/accessibility/AXRadioInput.h" | 6 #include "modules/accessibility/AXRadioInput.h" | 
| 7 | 7 | 
| 8 #include "core/InputTypeNames.h" | 8 #include "core/InputTypeNames.h" | 
| 9 #include "core/dom/ElementTraversal.h" |  | 
| 10 #include "core/html/HTMLFormElement.h" |  | 
| 11 #include "core/html/HTMLInputElement.h" | 9 #include "core/html/HTMLInputElement.h" | 
|  | 10 #include "core/html/forms/RadioInputType.h" | 
| 12 #include "modules/accessibility/AXObjectCacheImpl.h" | 11 #include "modules/accessibility/AXObjectCacheImpl.h" | 
| 13 | 12 | 
| 14 namespace blink { | 13 namespace blink { | 
| 15 | 14 | 
| 16 namespace { |  | 
| 17 |  | 
| 18 HTMLElement* nextElement(const HTMLElement& element, HTMLFormElement* stayWithin
     , bool forward) |  | 
| 19 { |  | 
| 20     return forward ? Traversal<HTMLElement>::next(element, static_cast<Node*>(st
     ayWithin)) : Traversal<HTMLElement>::previous(element, static_cast<Node*>(stayWi
     thin)); |  | 
| 21 } |  | 
| 22 |  | 
| 23 } // namespace |  | 
| 24 |  | 
| 25 using namespace HTMLNames; | 15 using namespace HTMLNames; | 
| 26 | 16 | 
| 27 AXRadioInput::AXRadioInput(LayoutObject* layoutObject, AXObjectCacheImpl& axObje
     ctCache) | 17 AXRadioInput::AXRadioInput(LayoutObject* layoutObject, AXObjectCacheImpl& axObje
     ctCache) | 
| 28     : AXLayoutObject(layoutObject, axObjectCache) | 18     : AXLayoutObject(layoutObject, axObjectCache) | 
| 29 { | 19 { | 
| 30     // Updates posInSet and setSize for the current object and the next objects. | 20     // Updates posInSet and setSize for the current object and the next objects. | 
| 31     if (!calculatePosInSet()) | 21     if (!calculatePosInSet()) | 
| 32         return; | 22         return; | 
| 33     // When a new object is inserted, it needs to update setSize for the previou
     s objects. | 23     // When a new object is inserted, it needs to update setSize for the previou
     s objects. | 
| 34     requestUpdateToNextNode(false); | 24     requestUpdateToNextNode(false); | 
| 35 } | 25 } | 
| 36 | 26 | 
| 37 AXRadioInput* AXRadioInput::create(LayoutObject* layoutObject, AXObjectCacheImpl
     & axObjectCache) | 27 AXRadioInput* AXRadioInput::create(LayoutObject* layoutObject, AXObjectCacheImpl
     & axObjectCache) | 
| 38 { | 28 { | 
| 39     return new AXRadioInput(layoutObject, axObjectCache); | 29     return new AXRadioInput(layoutObject, axObjectCache); | 
| 40 } | 30 } | 
| 41 | 31 | 
| 42 void AXRadioInput::updatePosAndSetSize(int position) | 32 void AXRadioInput::updatePosAndSetSize(int position) | 
| 43 { | 33 { | 
| 44     if (position) | 34     if (position) | 
| 45         m_posInSet = position; | 35         m_posInSet = position; | 
| 46     m_setSize = sizeOfRadioGroup(); | 36     m_setSize = sizeOfRadioGroup(); | 
| 47 } | 37 } | 
| 48 | 38 | 
| 49 void AXRadioInput::requestUpdateToNextNode(bool forward) | 39 void AXRadioInput::requestUpdateToNextNode(bool forward) | 
| 50 { | 40 { | 
| 51     HTMLInputElement* nextElement = findNextRadioButtonInGroup(element(), forwar
     d); | 41     HTMLInputElement* nextElement = RadioInputType::nextRadioButtonInGroup(eleme
     nt(), forward); | 
| 52     AXObject* nextAXobject = axObjectCache().get(nextElement); | 42     AXObject* nextAXobject = axObjectCache().get(nextElement); | 
| 53     if (!nextAXobject || !nextAXobject->isAXRadioInput()) | 43     if (!nextAXobject || !nextAXobject->isAXRadioInput()) | 
| 54         return; | 44         return; | 
| 55 | 45 | 
| 56     int position = 0; | 46     int position = 0; | 
| 57     if (forward) | 47     if (forward) | 
| 58         position = posInSet() + 1; | 48         position = posInSet() + 1; | 
| 59     // If it is backward, it keeps position as positions are already assigned fo
     r previous objects. | 49     // If it is backward, it keeps position as positions are already assigned fo
     r previous objects. | 
| 60     // updatePosAndSetSize() is called with '0' and it doesn't modify m_posInSet
      and updates m_setSize as size is increased. | 50     // updatePosAndSetSize() is called with '0' and it doesn't modify m_posInSet
      and updates m_setSize as size is increased. | 
| 61 | 51 | 
| 62     toAXRadioInput(nextAXobject)->updatePosAndSetSize(position); | 52     toAXRadioInput(nextAXobject)->updatePosAndSetSize(position); | 
| 63     axObjectCache().postNotification(nextAXobject, AXObjectCacheImpl::AXAriaAttr
     ibuteChanged); | 53     axObjectCache().postNotification(nextAXobject, AXObjectCacheImpl::AXAriaAttr
     ibuteChanged); | 
| 64     toAXRadioInput(nextAXobject)->requestUpdateToNextNode(forward); | 54     toAXRadioInput(nextAXobject)->requestUpdateToNextNode(forward); | 
| 65 } | 55 } | 
| 66 | 56 | 
| 67 HTMLInputElement* AXRadioInput::findFirstRadioButtonInGroup(HTMLInputElement* cu
     rrent) const | 57 HTMLInputElement* AXRadioInput::findFirstRadioButtonInGroup(HTMLInputElement* cu
     rrent) const | 
| 68 { | 58 { | 
| 69     while (HTMLInputElement* prevElement = findNextRadioButtonInGroup(current, f
     alse)) | 59     while (HTMLInputElement* prevElement = RadioInputType::nextRadioButtonInGrou
     p(current, false)) | 
| 70         current = prevElement; | 60         current = prevElement; | 
| 71     return current; | 61     return current; | 
| 72 } | 62 } | 
| 73 | 63 | 
| 74 int AXRadioInput::posInSet() const | 64 int AXRadioInput::posInSet() const | 
| 75 { | 65 { | 
| 76     if (hasAttribute(aria_posinsetAttr)) | 66     if (hasAttribute(aria_posinsetAttr)) | 
| 77         return getAttribute(aria_posinsetAttr).toInt(); | 67         return getAttribute(aria_posinsetAttr).toInt(); | 
| 78     return m_posInSet; | 68     return m_posInSet; | 
| 79 } | 69 } | 
| 80 | 70 | 
| 81 int AXRadioInput::setSize() const | 71 int AXRadioInput::setSize() const | 
| 82 { | 72 { | 
| 83     if (hasAttribute(aria_setsizeAttr)) | 73     if (hasAttribute(aria_setsizeAttr)) | 
| 84         return getAttribute(aria_setsizeAttr).toInt(); | 74         return getAttribute(aria_setsizeAttr).toInt(); | 
| 85     return m_setSize; | 75     return m_setSize; | 
| 86 } | 76 } | 
| 87 | 77 | 
| 88 bool AXRadioInput::calculatePosInSet() | 78 bool AXRadioInput::calculatePosInSet() | 
| 89 { | 79 { | 
| 90     // Calculate 'posInSet' attribute when AXRadioInputs need to be updated | 80     // Calculate 'posInSet' attribute when AXRadioInputs need to be updated | 
| 91     // as a new AXRadioInput Object is added or one of objects from RadioGroup i
     s removed. | 81     // as a new AXRadioInput Object is added or one of objects from RadioGroup i
     s removed. | 
| 92     bool needToUpdatePrev = false; | 82     bool needToUpdatePrev = false; | 
| 93     int position = 1; | 83     int position = 1; | 
| 94     HTMLInputElement* prevElement = findNextRadioButtonInGroup(element(), false)
     ; | 84     HTMLInputElement* prevElement = RadioInputType::nextRadioButtonInGroup(eleme
     nt(), false); | 
| 95     if (prevElement) { | 85     if (prevElement) { | 
| 96         AXObject* object = axObjectCache().get(prevElement); | 86         AXObject* object = axObjectCache().get(prevElement); | 
| 97         // If the previous element doesn't have AXObject yet, caculate position 
     from the first element. | 87         // If the previous element doesn't have AXObject yet, caculate position 
     from the first element. | 
| 98         // Otherwise, get position from the previous AXObject. | 88         // Otherwise, get position from the previous AXObject. | 
| 99         if (!object || !object->isAXRadioInput()) { | 89         if (!object || !object->isAXRadioInput()) { | 
| 100             position = countFromFirstElement(); | 90             position = countFromFirstElement(); | 
| 101         } else { | 91         } else { | 
| 102             position = object->posInSet() + 1; | 92             position = object->posInSet() + 1; | 
| 103             // It returns true if previous objects need to be updated. | 93             // It returns true if previous objects need to be updated. | 
| 104             // When AX tree exists already and a new node is inserted, | 94             // When AX tree exists already and a new node is inserted, | 
| 105             // as updating is started from the inserted node, | 95             // as updating is started from the inserted node, | 
| 106             // we need to update setSize for previous nodes. | 96             // we need to update setSize for previous nodes. | 
| 107             if (setSize() != object->setSize()) | 97             if (setSize() != object->setSize()) | 
| 108                 needToUpdatePrev = true; | 98                 needToUpdatePrev = true; | 
| 109         } | 99         } | 
| 110     } | 100     } | 
| 111     updatePosAndSetSize(position); | 101     updatePosAndSetSize(position); | 
| 112 | 102 | 
| 113     // If it is not the last element, request update to the next node. | 103     // If it is not the last element, request update to the next node. | 
| 114     if (position != setSize()) | 104     if (position != setSize()) | 
| 115         requestUpdateToNextNode(true); | 105         requestUpdateToNextNode(true); | 
| 116     return needToUpdatePrev; | 106     return needToUpdatePrev; | 
| 117 } | 107 } | 
| 118 | 108 | 
| 119 HTMLInputElement* AXRadioInput::findNextRadioButtonInGroup(HTMLInputElement* cur
     rent, bool forward) const |  | 
| 120 { |  | 
| 121     for (HTMLElement* htmlElement = nextElement(*current, current->form(), forwa
     rd); htmlElement; htmlElement = nextElement(*htmlElement, current->form(), forwa
     rd)) { |  | 
| 122         if (!isHTMLInputElement(*htmlElement)) |  | 
| 123             continue; |  | 
| 124         HTMLInputElement* inputElement = toHTMLInputElement(htmlElement); |  | 
| 125         if (current->form() == inputElement->form() && inputElement->type() == I
     nputTypeNames::radio && inputElement->name() == current->name()) |  | 
| 126             return inputElement; |  | 
| 127     } |  | 
| 128     return nullptr; |  | 
| 129 } |  | 
| 130 |  | 
| 131 int AXRadioInput::countFromFirstElement() const | 109 int AXRadioInput::countFromFirstElement() const | 
| 132 { | 110 { | 
| 133     int count = 1; | 111     int count = 1; | 
| 134     HTMLInputElement* current = element(); | 112     HTMLInputElement* current = element(); | 
| 135     while (HTMLInputElement* prevElement = findNextRadioButtonInGroup(current, f
     alse)) { | 113     while (HTMLInputElement* prevElement = RadioInputType::nextRadioButtonInGrou
     p(current, false)) { | 
| 136         current = prevElement; | 114         current = prevElement; | 
| 137         count++; | 115         count++; | 
| 138     } | 116     } | 
| 139     return count; | 117     return count; | 
| 140 } | 118 } | 
| 141 | 119 | 
| 142 HTMLInputElement* AXRadioInput::element() const | 120 HTMLInputElement* AXRadioInput::element() const | 
| 143 { | 121 { | 
| 144     return toHTMLInputElement(m_layoutObject->node()); | 122     return toHTMLInputElement(m_layoutObject->node()); | 
| 145 } | 123 } | 
| 146 | 124 | 
| 147 int AXRadioInput::sizeOfRadioGroup() const | 125 int AXRadioInput::sizeOfRadioGroup() const | 
| 148 { | 126 { | 
| 149     int size = element()->sizeOfRadioGroup(); | 127     int size = element()->sizeOfRadioGroup(); | 
| 150     // If it has no size in Group, it means that there is only itself. | 128     // If it has no size in Group, it means that there is only itself. | 
| 151     if (!size) | 129     if (!size) | 
| 152         return 1; | 130         return 1; | 
| 153     return size; | 131     return size; | 
| 154 } | 132 } | 
| 155 | 133 | 
| 156 } // namespace blink | 134 } // namespace blink | 
| OLD | NEW | 
|---|