Keep auxilliary media objects on the heap always.
[chromium-blink-merge.git] / third_party / WebKit / Source / core / html / FormAssociatedElement.cpp
blobffb7151311a819c639d716cc4bc03bb9b2f45630
1 /*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * (C) 2001 Dirk Mueller (mueller@kde.org)
5 * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
6 * (C) 2006 Alexey Proskuryakov (ap@nypop.com)
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
18 * You should have received a copy of the GNU Library General Public License
19 * along with this library; see the file COPYING.LIB. If not, write to
20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
25 #include "config.h"
26 #include "core/html/FormAssociatedElement.h"
28 #include "core/HTMLNames.h"
29 #include "core/dom/IdTargetObserver.h"
30 #include "core/dom/NodeTraversal.h"
31 #include "core/html/HTMLFormControlElement.h"
32 #include "core/html/HTMLFormElement.h"
33 #include "core/html/HTMLLabelElement.h"
34 #include "core/html/HTMLObjectElement.h"
35 #include "core/html/ValidityState.h"
37 namespace blink {
39 using namespace HTMLNames;
41 class FormAttributeTargetObserver : public IdTargetObserver {
42 WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED(FormAttributeTargetObserver);
43 public:
44 static PassOwnPtrWillBeRawPtr<FormAttributeTargetObserver> create(const AtomicString& id, FormAssociatedElement*);
45 DECLARE_VIRTUAL_TRACE();
46 void idTargetChanged() override;
48 private:
49 FormAttributeTargetObserver(const AtomicString& id, FormAssociatedElement*);
51 RawPtrWillBeMember<FormAssociatedElement> m_element;
54 FormAssociatedElement::FormAssociatedElement()
55 : m_formWasSetByParser(false)
59 FormAssociatedElement::~FormAssociatedElement()
61 // We can't call setForm here because it contains virtual calls.
64 DEFINE_TRACE(FormAssociatedElement)
66 visitor->trace(m_formAttributeTargetObserver);
67 visitor->trace(m_form);
68 visitor->trace(m_validityState);
71 ValidityState* FormAssociatedElement::validity()
73 if (!m_validityState)
74 m_validityState = ValidityState::create(this);
76 return m_validityState.get();
79 void FormAssociatedElement::didMoveToNewDocument(Document& oldDocument)
81 HTMLElement* element = toHTMLElement(this);
82 if (element->fastHasAttribute(formAttr))
83 setFormAttributeTargetObserver(nullptr);
86 void FormAssociatedElement::insertedInto(ContainerNode* insertionPoint)
88 if (!m_formWasSetByParser || !m_form || NodeTraversal::highestAncestorOrSelf(*insertionPoint) != NodeTraversal::highestAncestorOrSelf(*m_form.get()))
89 resetFormOwner();
91 if (!insertionPoint->inDocument())
92 return;
94 HTMLElement* element = toHTMLElement(this);
95 if (element->fastHasAttribute(formAttr))
96 resetFormAttributeTargetObserver();
99 void FormAssociatedElement::removedFrom(ContainerNode* insertionPoint)
101 HTMLElement* element = toHTMLElement(this);
102 if (insertionPoint->inDocument() && element->fastHasAttribute(formAttr)) {
103 setFormAttributeTargetObserver(nullptr);
104 resetFormOwner();
105 return;
107 // If the form and element are both in the same tree, preserve the connection to the form.
108 // Otherwise, null out our form and remove ourselves from the form's list of elements.
109 if (m_form && NodeTraversal::highestAncestorOrSelf(*element) != NodeTraversal::highestAncestorOrSelf(*m_form.get()))
110 resetFormOwner();
113 HTMLFormElement* FormAssociatedElement::findAssociatedForm(const HTMLElement* element)
115 const AtomicString& formId(element->fastGetAttribute(formAttr));
116 // 3. If the element is reassociateable, has a form content attribute, and
117 // is itself in a Document, then run these substeps:
118 if (!formId.isNull() && element->inDocument()) {
119 // 3.1. If the first element in the Document to have an ID that is
120 // case-sensitively equal to the element's form content attribute's
121 // value is a form element, then associate the form-associated element
122 // with that form element.
123 // 3.2. Abort the "reset the form owner" steps.
124 Element* newFormCandidate = element->treeScope().getElementById(formId);
125 return isHTMLFormElement(newFormCandidate) ? toHTMLFormElement(newFormCandidate) : 0;
127 // 4. Otherwise, if the form-associated element in question has an ancestor
128 // form element, then associate the form-associated element with the nearest
129 // such ancestor form element.
130 return element->findFormAncestor();
133 void FormAssociatedElement::formRemovedFromTree(const Node& formRoot)
135 ASSERT(m_form);
136 if (NodeTraversal::highestAncestorOrSelf(toHTMLElement(*this)) == formRoot)
137 return;
138 resetFormOwner();
141 void FormAssociatedElement::associateByParser(HTMLFormElement* form)
143 if (form && form->inDocument()) {
144 m_formWasSetByParser = true;
145 setForm(form);
146 form->didAssociateByParser();
150 void FormAssociatedElement::setForm(HTMLFormElement* newForm)
152 if (m_form.get() == newForm)
153 return;
154 willChangeForm();
155 if (m_form)
156 m_form->disassociate(*this);
157 if (newForm) {
158 #if ENABLE(OILPAN)
159 m_form = newForm;
160 #else
161 m_form = newForm->createWeakPtr();
162 #endif
163 m_form->associate(*this);
164 } else {
165 #if ENABLE(OILPAN)
166 m_form = nullptr;
167 #else
168 m_form = WeakPtr<HTMLFormElement>();
169 #endif
171 didChangeForm();
174 void FormAssociatedElement::willChangeForm()
178 void FormAssociatedElement::didChangeForm()
180 if (!m_formWasSetByParser && m_form && m_form->inDocument()) {
181 HTMLElement* element = toHTMLElement(this);
182 element->document().didAssociateFormControl(element);
186 void FormAssociatedElement::resetFormOwner()
188 m_formWasSetByParser = false;
189 HTMLElement* element = toHTMLElement(this);
190 const AtomicString& formId(element->fastGetAttribute(formAttr));
191 HTMLFormElement* nearestForm = element->findFormAncestor();
192 // 1. If the element's form owner is not null, and either the element is not
193 // reassociateable or its form content attribute is not present, and the
194 // element's form owner is its nearest form element ancestor after the
195 // change to the ancestor chain, then do nothing, and abort these steps.
196 if (m_form && formId.isNull() && m_form.get() == nearestForm)
197 return;
199 setForm(findAssociatedForm(element));
202 void FormAssociatedElement::formAttributeChanged()
204 resetFormOwner();
205 resetFormAttributeTargetObserver();
208 bool FormAssociatedElement::customError() const
210 const HTMLElement* element = toHTMLElement(this);
211 return element->willValidate() && !m_customValidationMessage.isEmpty();
214 bool FormAssociatedElement::hasBadInput() const
216 return false;
219 bool FormAssociatedElement::patternMismatch() const
221 return false;
224 bool FormAssociatedElement::rangeOverflow() const
226 return false;
229 bool FormAssociatedElement::rangeUnderflow() const
231 return false;
234 bool FormAssociatedElement::stepMismatch() const
236 return false;
239 bool FormAssociatedElement::tooLong() const
241 return false;
244 bool FormAssociatedElement::tooShort() const
246 return false;
249 bool FormAssociatedElement::typeMismatch() const
251 return false;
254 bool FormAssociatedElement::valid() const
256 bool someError = typeMismatch() || stepMismatch() || rangeUnderflow() || rangeOverflow()
257 || tooLong() || tooShort() || patternMismatch() || valueMissing() || hasBadInput()
258 || customError();
259 return !someError;
262 bool FormAssociatedElement::valueMissing() const
264 return false;
267 String FormAssociatedElement::customValidationMessage() const
269 return m_customValidationMessage;
272 String FormAssociatedElement::validationMessage() const
274 return customError() ? m_customValidationMessage : String();
277 void FormAssociatedElement::setCustomValidity(const String& error)
279 m_customValidationMessage = error;
282 void FormAssociatedElement::setFormAttributeTargetObserver(PassOwnPtrWillBeRawPtr<FormAttributeTargetObserver> newObserver)
284 if (m_formAttributeTargetObserver)
285 m_formAttributeTargetObserver->unregister();
286 m_formAttributeTargetObserver = newObserver;
289 void FormAssociatedElement::resetFormAttributeTargetObserver()
291 HTMLElement* element = toHTMLElement(this);
292 const AtomicString& formId(element->fastGetAttribute(formAttr));
293 if (!formId.isNull() && element->inDocument())
294 setFormAttributeTargetObserver(FormAttributeTargetObserver::create(formId, this));
295 else
296 setFormAttributeTargetObserver(nullptr);
299 void FormAssociatedElement::formAttributeTargetChanged()
301 resetFormOwner();
304 const AtomicString& FormAssociatedElement::name() const
306 const AtomicString& name = toHTMLElement(this)->getNameAttribute();
307 return name.isNull() ? emptyAtom : name;
310 bool FormAssociatedElement::isFormControlElementWithState() const
312 return false;
315 const HTMLElement& toHTMLElement(const FormAssociatedElement& associatedElement)
317 if (associatedElement.isFormControlElement())
318 return toHTMLFormControlElement(associatedElement);
319 if (associatedElement.isLabelElement())
320 return toHTMLLabelElement(associatedElement);
321 return toHTMLObjectElement(associatedElement);
324 const HTMLElement* toHTMLElement(const FormAssociatedElement* associatedElement)
326 ASSERT(associatedElement);
327 return &toHTMLElement(*associatedElement);
330 HTMLElement* toHTMLElement(FormAssociatedElement* associatedElement)
332 return const_cast<HTMLElement*>(toHTMLElement(static_cast<const FormAssociatedElement*>(associatedElement)));
335 HTMLElement& toHTMLElement(FormAssociatedElement& associatedElement)
337 return const_cast<HTMLElement&>(toHTMLElement(static_cast<const FormAssociatedElement&>(associatedElement)));
340 PassOwnPtrWillBeRawPtr<FormAttributeTargetObserver> FormAttributeTargetObserver::create(const AtomicString& id, FormAssociatedElement* element)
342 return adoptPtrWillBeNoop(new FormAttributeTargetObserver(id, element));
345 FormAttributeTargetObserver::FormAttributeTargetObserver(const AtomicString& id, FormAssociatedElement* element)
346 : IdTargetObserver(toHTMLElement(element)->treeScope().idTargetObserverRegistry(), id)
347 , m_element(element)
351 DEFINE_TRACE(FormAttributeTargetObserver)
353 visitor->trace(m_element);
354 IdTargetObserver::trace(visitor);
357 void FormAttributeTargetObserver::idTargetChanged()
359 m_element->formAttributeTargetChanged();
362 } // namespace blink