| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved. | 2 * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * This library is free software; you can redistribute it and/or | 4 * This library is free software; you can redistribute it and/or |
| 5 * modify it under the terms of the GNU Library General Public | 5 * modify it under the terms of the GNU Library General Public |
| 6 * License as published by the Free Software Foundation; either | 6 * License as published by the Free Software Foundation; either |
| 7 * version 2 of the License, or (at your option) any later version. | 7 * version 2 of the License, or (at your option) any later version. |
| 8 * | 8 * |
| 9 * This library is distributed in the hope that it will be useful, | 9 * This library is distributed in the hope that it will be useful, |
| 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 12 * Library General Public License for more details. | 12 * Library General Public License for more details. |
| 13 * | 13 * |
| 14 * You should have received a copy of the GNU Library General Public License | 14 * You should have received a copy of the GNU Library General Public License |
| 15 * along with this library; see the file COPYING.LIB. If not, write to | 15 * along with this library; see the file COPYING.LIB. If not, write to |
| 16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | 16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
| 17 * Boston, MA 02110-1301, USA. | 17 * Boston, MA 02110-1301, USA. |
| 18 * | 18 * |
| 19 */ | 19 */ |
| 20 | 20 |
| 21 #include "config.h" | 21 #include "config.h" |
| 22 #include "core/html/forms/RadioButtonGroupScope.h" | 22 #include "core/html/forms/RadioButtonGroupScope.h" |
| 23 | 23 |
| 24 #include "core/InputTypeNames.h" |
| 24 #include "core/html/HTMLInputElement.h" | 25 #include "core/html/HTMLInputElement.h" |
| 25 #include "wtf/HashSet.h" | 26 #include "wtf/HashSet.h" |
| 26 | 27 |
| 27 namespace blink { | 28 namespace blink { |
| 28 | 29 |
| 29 class RadioButtonGroup : public NoBaseWillBeGarbageCollected<RadioButtonGroup> { | 30 class RadioButtonGroup : public NoBaseWillBeGarbageCollected<RadioButtonGroup> { |
| 30 WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED; | 31 WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED; |
| 31 public: | 32 public: |
| 32 static PassOwnPtrWillBeRawPtr<RadioButtonGroup> create(); | 33 static PassOwnPtrWillBeRawPtr<RadioButtonGroup> create(); |
| 33 bool isEmpty() const { return m_members.isEmpty(); } | 34 bool isEmpty() const { return m_members.isEmpty(); } |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 73 HTMLInputElement* oldCheckedButton = m_checkedButton; | 74 HTMLInputElement* oldCheckedButton = m_checkedButton; |
| 74 if (oldCheckedButton == button) | 75 if (oldCheckedButton == button) |
| 75 return; | 76 return; |
| 76 m_checkedButton = button; | 77 m_checkedButton = button; |
| 77 if (oldCheckedButton) | 78 if (oldCheckedButton) |
| 78 oldCheckedButton->setChecked(false); | 79 oldCheckedButton->setChecked(false); |
| 79 } | 80 } |
| 80 | 81 |
| 81 void RadioButtonGroup::add(HTMLInputElement* button) | 82 void RadioButtonGroup::add(HTMLInputElement* button) |
| 82 { | 83 { |
| 83 ASSERT(button->isRadioButton()); | 84 ASSERT(button->type() == InputTypeNames::radio); |
| 84 if (!m_members.add(button).isNewEntry) | 85 if (!m_members.add(button).isNewEntry) |
| 85 return; | 86 return; |
| 86 bool groupWasValid = isValid(); | 87 bool groupWasValid = isValid(); |
| 87 if (button->isRequired()) | 88 if (button->isRequired()) |
| 88 ++m_requiredCount; | 89 ++m_requiredCount; |
| 89 if (button->checked()) | 90 if (button->checked()) |
| 90 setCheckedButton(button); | 91 setCheckedButton(button); |
| 91 | 92 |
| 92 bool groupIsValid = isValid(); | 93 bool groupIsValid = isValid(); |
| 93 if (groupWasValid != groupIsValid) { | 94 if (groupWasValid != groupIsValid) { |
| 94 setNeedsValidityCheckForAllButtons(); | 95 setNeedsValidityCheckForAllButtons(); |
| 95 } else if (!groupIsValid) { | 96 } else if (!groupIsValid) { |
| 96 // A radio button not in a group is always valid. We need to make it | 97 // A radio button not in a group is always valid. We need to make it |
| 97 // invalid only if the group is invalid. | 98 // invalid only if the group is invalid. |
| 98 button->setNeedsValidityCheck(); | 99 button->setNeedsValidityCheck(); |
| 99 } | 100 } |
| 100 } | 101 } |
| 101 | 102 |
| 102 void RadioButtonGroup::updateCheckedState(HTMLInputElement* button) | 103 void RadioButtonGroup::updateCheckedState(HTMLInputElement* button) |
| 103 { | 104 { |
| 104 ASSERT(button->isRadioButton()); | 105 ASSERT(button->type() == InputTypeNames::radio); |
| 105 ASSERT(m_members.contains(button)); | 106 ASSERT(m_members.contains(button)); |
| 106 bool wasValid = isValid(); | 107 bool wasValid = isValid(); |
| 107 if (button->checked()) { | 108 if (button->checked()) { |
| 108 setCheckedButton(button); | 109 setCheckedButton(button); |
| 109 } else { | 110 } else { |
| 110 if (m_checkedButton == button) | 111 if (m_checkedButton == button) |
| 111 m_checkedButton = nullptr; | 112 m_checkedButton = nullptr; |
| 112 } | 113 } |
| 113 if (wasValid != isValid()) | 114 if (wasValid != isValid()) |
| 114 setNeedsValidityCheckForAllButtons(); | 115 setNeedsValidityCheckForAllButtons(); |
| 115 typedef WillBeHeapHashSet<RawPtrWillBeMember<HTMLInputElement> >::const_iter
ator Iterator; | 116 typedef WillBeHeapHashSet<RawPtrWillBeMember<HTMLInputElement> >::const_iter
ator Iterator; |
| 116 Iterator end = m_members.end(); | 117 Iterator end = m_members.end(); |
| 117 for (Iterator it = m_members.begin(); it != end; ++it) { | 118 for (Iterator it = m_members.begin(); it != end; ++it) { |
| 118 (*it)->didAffectSelector(AffectedSelectorIndeterminate); | 119 (*it)->didAffectSelector(AffectedSelectorIndeterminate); |
| 119 } | 120 } |
| 120 } | 121 } |
| 121 | 122 |
| 122 void RadioButtonGroup::requiredAttributeChanged(HTMLInputElement* button) | 123 void RadioButtonGroup::requiredAttributeChanged(HTMLInputElement* button) |
| 123 { | 124 { |
| 124 ASSERT(button->isRadioButton()); | 125 ASSERT(button->type() == InputTypeNames::radio); |
| 125 ASSERT(m_members.contains(button)); | 126 ASSERT(m_members.contains(button)); |
| 126 bool wasValid = isValid(); | 127 bool wasValid = isValid(); |
| 127 if (button->isRequired()) { | 128 if (button->isRequired()) { |
| 128 ++m_requiredCount; | 129 ++m_requiredCount; |
| 129 } else { | 130 } else { |
| 130 ASSERT(m_requiredCount); | 131 ASSERT(m_requiredCount); |
| 131 --m_requiredCount; | 132 --m_requiredCount; |
| 132 } | 133 } |
| 133 if (wasValid != isValid()) | 134 if (wasValid != isValid()) |
| 134 setNeedsValidityCheckForAllButtons(); | 135 setNeedsValidityCheckForAllButtons(); |
| 135 } | 136 } |
| 136 | 137 |
| 137 void RadioButtonGroup::remove(HTMLInputElement* button) | 138 void RadioButtonGroup::remove(HTMLInputElement* button) |
| 138 { | 139 { |
| 139 ASSERT(button->isRadioButton()); | 140 ASSERT(button->type() == InputTypeNames::radio); |
| 140 WillBeHeapHashSet<RawPtrWillBeMember<HTMLInputElement> >::iterator it = m_me
mbers.find(button); | 141 WillBeHeapHashSet<RawPtrWillBeMember<HTMLInputElement> >::iterator it = m_me
mbers.find(button); |
| 141 if (it == m_members.end()) | 142 if (it == m_members.end()) |
| 142 return; | 143 return; |
| 143 bool wasValid = isValid(); | 144 bool wasValid = isValid(); |
| 144 m_members.remove(it); | 145 m_members.remove(it); |
| 145 if (button->isRequired()) { | 146 if (button->isRequired()) { |
| 146 ASSERT(m_requiredCount); | 147 ASSERT(m_requiredCount); |
| 147 --m_requiredCount; | 148 --m_requiredCount; |
| 148 } | 149 } |
| 149 if (m_checkedButton == button) | 150 if (m_checkedButton == button) |
| (...skipping 11 matching lines...) Expand all Loading... |
| 161 button->setNeedsValidityCheck(); | 162 button->setNeedsValidityCheck(); |
| 162 } | 163 } |
| 163 } | 164 } |
| 164 | 165 |
| 165 void RadioButtonGroup::setNeedsValidityCheckForAllButtons() | 166 void RadioButtonGroup::setNeedsValidityCheckForAllButtons() |
| 166 { | 167 { |
| 167 typedef WillBeHeapHashSet<RawPtrWillBeMember<HTMLInputElement> >::const_iter
ator Iterator; | 168 typedef WillBeHeapHashSet<RawPtrWillBeMember<HTMLInputElement> >::const_iter
ator Iterator; |
| 168 Iterator end = m_members.end(); | 169 Iterator end = m_members.end(); |
| 169 for (Iterator it = m_members.begin(); it != end; ++it) { | 170 for (Iterator it = m_members.begin(); it != end; ++it) { |
| 170 HTMLInputElement* button = *it; | 171 HTMLInputElement* button = *it; |
| 171 ASSERT(button->isRadioButton()); | 172 ASSERT(button->type() == InputTypeNames::radio); |
| 172 button->setNeedsValidityCheck(); | 173 button->setNeedsValidityCheck(); |
| 173 } | 174 } |
| 174 } | 175 } |
| 175 | 176 |
| 176 bool RadioButtonGroup::contains(HTMLInputElement* button) const | 177 bool RadioButtonGroup::contains(HTMLInputElement* button) const |
| 177 { | 178 { |
| 178 return m_members.contains(button); | 179 return m_members.contains(button); |
| 179 } | 180 } |
| 180 | 181 |
| 181 void RadioButtonGroup::trace(Visitor* visitor) | 182 void RadioButtonGroup::trace(Visitor* visitor) |
| (...skipping 12 matching lines...) Expand all Loading... |
| 194 RadioButtonGroupScope::RadioButtonGroupScope() | 195 RadioButtonGroupScope::RadioButtonGroupScope() |
| 195 { | 196 { |
| 196 } | 197 } |
| 197 | 198 |
| 198 RadioButtonGroupScope::~RadioButtonGroupScope() | 199 RadioButtonGroupScope::~RadioButtonGroupScope() |
| 199 { | 200 { |
| 200 } | 201 } |
| 201 | 202 |
| 202 void RadioButtonGroupScope::addButton(HTMLInputElement* element) | 203 void RadioButtonGroupScope::addButton(HTMLInputElement* element) |
| 203 { | 204 { |
| 204 ASSERT(element->isRadioButton()); | 205 ASSERT(element->type() == InputTypeNames::radio); |
| 205 if (element->name().isEmpty()) | 206 if (element->name().isEmpty()) |
| 206 return; | 207 return; |
| 207 | 208 |
| 208 if (!m_nameToGroupMap) | 209 if (!m_nameToGroupMap) |
| 209 m_nameToGroupMap = adoptPtrWillBeNoop(new NameToGroupMap); | 210 m_nameToGroupMap = adoptPtrWillBeNoop(new NameToGroupMap); |
| 210 | 211 |
| 211 OwnPtrWillBeMember<RadioButtonGroup>& group = m_nameToGroupMap->add(element-
>name(), nullptr).storedValue->value; | 212 OwnPtrWillBeMember<RadioButtonGroup>& group = m_nameToGroupMap->add(element-
>name(), nullptr).storedValue->value; |
| 212 if (!group) | 213 if (!group) |
| 213 group = RadioButtonGroup::create(); | 214 group = RadioButtonGroup::create(); |
| 214 group->add(element); | 215 group->add(element); |
| 215 } | 216 } |
| 216 | 217 |
| 217 void RadioButtonGroupScope::updateCheckedState(HTMLInputElement* element) | 218 void RadioButtonGroupScope::updateCheckedState(HTMLInputElement* element) |
| 218 { | 219 { |
| 219 ASSERT(element->isRadioButton()); | 220 ASSERT(element->type() == InputTypeNames::radio); |
| 220 if (element->name().isEmpty()) | 221 if (element->name().isEmpty()) |
| 221 return; | 222 return; |
| 222 ASSERT(m_nameToGroupMap); | 223 ASSERT(m_nameToGroupMap); |
| 223 if (!m_nameToGroupMap) | 224 if (!m_nameToGroupMap) |
| 224 return; | 225 return; |
| 225 RadioButtonGroup* group = m_nameToGroupMap->get(element->name()); | 226 RadioButtonGroup* group = m_nameToGroupMap->get(element->name()); |
| 226 ASSERT(group); | 227 ASSERT(group); |
| 227 group->updateCheckedState(element); | 228 group->updateCheckedState(element); |
| 228 } | 229 } |
| 229 | 230 |
| 230 void RadioButtonGroupScope::requiredAttributeChanged(HTMLInputElement* element) | 231 void RadioButtonGroupScope::requiredAttributeChanged(HTMLInputElement* element) |
| 231 { | 232 { |
| 232 ASSERT(element->isRadioButton()); | 233 ASSERT(element->type() == InputTypeNames::radio); |
| 233 if (element->name().isEmpty()) | 234 if (element->name().isEmpty()) |
| 234 return; | 235 return; |
| 235 ASSERT(m_nameToGroupMap); | 236 ASSERT(m_nameToGroupMap); |
| 236 if (!m_nameToGroupMap) | 237 if (!m_nameToGroupMap) |
| 237 return; | 238 return; |
| 238 RadioButtonGroup* group = m_nameToGroupMap->get(element->name()); | 239 RadioButtonGroup* group = m_nameToGroupMap->get(element->name()); |
| 239 ASSERT(group); | 240 ASSERT(group); |
| 240 group->requiredAttributeChanged(element); | 241 group->requiredAttributeChanged(element); |
| 241 } | 242 } |
| 242 | 243 |
| 243 HTMLInputElement* RadioButtonGroupScope::checkedButtonForGroup(const AtomicStrin
g& name) const | 244 HTMLInputElement* RadioButtonGroupScope::checkedButtonForGroup(const AtomicStrin
g& name) const |
| 244 { | 245 { |
| 245 if (!m_nameToGroupMap) | 246 if (!m_nameToGroupMap) |
| 246 return 0; | 247 return 0; |
| 247 RadioButtonGroup* group = m_nameToGroupMap->get(name); | 248 RadioButtonGroup* group = m_nameToGroupMap->get(name); |
| 248 return group ? group->checkedButton() : 0; | 249 return group ? group->checkedButton() : 0; |
| 249 } | 250 } |
| 250 | 251 |
| 251 bool RadioButtonGroupScope::isInRequiredGroup(HTMLInputElement* element) const | 252 bool RadioButtonGroupScope::isInRequiredGroup(HTMLInputElement* element) const |
| 252 { | 253 { |
| 253 ASSERT(element->isRadioButton()); | 254 ASSERT(element->type() == InputTypeNames::radio); |
| 254 if (element->name().isEmpty()) | 255 if (element->name().isEmpty()) |
| 255 return false; | 256 return false; |
| 256 if (!m_nameToGroupMap) | 257 if (!m_nameToGroupMap) |
| 257 return false; | 258 return false; |
| 258 RadioButtonGroup* group = m_nameToGroupMap->get(element->name()); | 259 RadioButtonGroup* group = m_nameToGroupMap->get(element->name()); |
| 259 return group && group->isRequired() && group->contains(element); | 260 return group && group->isRequired() && group->contains(element); |
| 260 } | 261 } |
| 261 | 262 |
| 262 void RadioButtonGroupScope::removeButton(HTMLInputElement* element) | 263 void RadioButtonGroupScope::removeButton(HTMLInputElement* element) |
| 263 { | 264 { |
| 264 ASSERT(element->isRadioButton()); | 265 ASSERT(element->type() == InputTypeNames::radio); |
| 265 if (element->name().isEmpty()) | 266 if (element->name().isEmpty()) |
| 266 return; | 267 return; |
| 267 if (!m_nameToGroupMap) | 268 if (!m_nameToGroupMap) |
| 268 return; | 269 return; |
| 269 | 270 |
| 270 RadioButtonGroup* group = m_nameToGroupMap->get(element->name()); | 271 RadioButtonGroup* group = m_nameToGroupMap->get(element->name()); |
| 271 if (!group) | 272 if (!group) |
| 272 return; | 273 return; |
| 273 group->remove(element); | 274 group->remove(element); |
| 274 if (group->isEmpty()) { | 275 if (group->isEmpty()) { |
| 275 // We don't remove an empty RadioButtonGroup from m_nameToGroupMap for | 276 // We don't remove an empty RadioButtonGroup from m_nameToGroupMap for |
| 276 // better performance. | 277 // better performance. |
| 277 ASSERT(!group->isRequired()); | 278 ASSERT(!group->isRequired()); |
| 278 ASSERT_WITH_SECURITY_IMPLICATION(!group->checkedButton()); | 279 ASSERT_WITH_SECURITY_IMPLICATION(!group->checkedButton()); |
| 279 } | 280 } |
| 280 } | 281 } |
| 281 | 282 |
| 282 void RadioButtonGroupScope::trace(Visitor* visitor) | 283 void RadioButtonGroupScope::trace(Visitor* visitor) |
| 283 { | 284 { |
| 284 #if ENABLE(OILPAN) | 285 #if ENABLE(OILPAN) |
| 285 visitor->trace(m_nameToGroupMap); | 286 visitor->trace(m_nameToGroupMap); |
| 286 #endif | 287 #endif |
| 287 } | 288 } |
| 288 | 289 |
| 289 } // namespace | 290 } // namespace |
| OLD | NEW |