Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / html / FormAssociatedElement.cpp
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)
7  *
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.
12  *
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.
17  *
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.
22  *
23  */
24
25 #include "config.h"
26 #include "core/html/FormAssociatedElement.h"
27
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"
36
37 namespace blink {
38
39 using namespace HTMLNames;
40
41 class FormAttributeTargetObserver : public IdTargetObserver {
42     WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED;
43 public:
44     static PassOwnPtrWillBeRawPtr<FormAttributeTargetObserver> create(const AtomicString& id, FormAssociatedElement*);
45     virtual void trace(Visitor*) override;
46     virtual void idTargetChanged() override;
47
48 private:
49     FormAttributeTargetObserver(const AtomicString& id, FormAssociatedElement*);
50
51     RawPtrWillBeMember<FormAssociatedElement> m_element;
52 };
53
54 FormAssociatedElement::FormAssociatedElement()
55     : m_formWasSetByParser(false)
56 {
57 }
58
59 FormAssociatedElement::~FormAssociatedElement()
60 {
61     // We can't call setForm here because it contains virtual calls.
62 }
63
64 void FormAssociatedElement::trace(Visitor* visitor)
65 {
66     visitor->trace(m_formAttributeTargetObserver);
67     visitor->trace(m_form);
68     visitor->trace(m_validityState);
69 }
70
71 ValidityState* FormAssociatedElement::validity()
72 {
73     if (!m_validityState)
74         m_validityState = ValidityState::create(this);
75
76     return m_validityState.get();
77 }
78
79 void FormAssociatedElement::didMoveToNewDocument(Document& oldDocument)
80 {
81     HTMLElement* element = toHTMLElement(this);
82     if (element->fastHasAttribute(formAttr))
83         setFormAttributeTargetObserver(nullptr);
84 }
85
86 void FormAssociatedElement::insertedInto(ContainerNode* insertionPoint)
87 {
88     if (!m_formWasSetByParser || !m_form || NodeTraversal::highestAncestorOrSelf(*insertionPoint) != NodeTraversal::highestAncestorOrSelf(*m_form.get()))
89         resetFormOwner();
90
91     if (!insertionPoint->inDocument())
92         return;
93
94     HTMLElement* element = toHTMLElement(this);
95     if (element->fastHasAttribute(formAttr))
96         resetFormAttributeTargetObserver();
97 }
98
99 void FormAssociatedElement::removedFrom(ContainerNode* insertionPoint)
100 {
101     HTMLElement* element = toHTMLElement(this);
102     if (insertionPoint->inDocument() && element->fastHasAttribute(formAttr))
103         setFormAttributeTargetObserver(nullptr);
104     // If the form and element are both in the same tree, preserve the connection to the form.
105     // Otherwise, null out our form and remove ourselves from the form's list of elements.
106     if (m_form && NodeTraversal::highestAncestorOrSelf(*element) != NodeTraversal::highestAncestorOrSelf(*m_form.get()))
107         resetFormOwner();
108 }
109
110 HTMLFormElement* FormAssociatedElement::findAssociatedForm(const HTMLElement* element)
111 {
112     const AtomicString& formId(element->fastGetAttribute(formAttr));
113     // 3. If the element is reassociateable, has a form content attribute, and
114     // is itself in a Document, then run these substeps:
115     if (!formId.isNull() && element->inDocument()) {
116         // 3.1. If the first element in the Document to have an ID that is
117         // case-sensitively equal to the element's form content attribute's
118         // value is a form element, then associate the form-associated element
119         // with that form element.
120         // 3.2. Abort the "reset the form owner" steps.
121         Element* newFormCandidate = element->treeScope().getElementById(formId);
122         return isHTMLFormElement(newFormCandidate) ? toHTMLFormElement(newFormCandidate) : 0;
123     }
124     // 4. Otherwise, if the form-associated element in question has an ancestor
125     // form element, then associate the form-associated element with the nearest
126     // such ancestor form element.
127     return element->findFormAncestor();
128 }
129
130 void FormAssociatedElement::formRemovedFromTree(const Node& formRoot)
131 {
132     ASSERT(m_form);
133     if (NodeTraversal::highestAncestorOrSelf(toHTMLElement(*this)) == formRoot)
134         return;
135     resetFormOwner();
136 }
137
138 void FormAssociatedElement::associateByParser(HTMLFormElement* form)
139 {
140     if (form && form->inDocument()) {
141         m_formWasSetByParser = true;
142         setForm(form);
143         form->didAssociateByParser();
144     }
145 }
146
147 void FormAssociatedElement::setForm(HTMLFormElement* newForm)
148 {
149     if (m_form.get() == newForm)
150         return;
151     willChangeForm();
152     if (m_form)
153         m_form->disassociate(*this);
154     if (newForm) {
155 #if ENABLE(OILPAN)
156         m_form = newForm;
157 #else
158         m_form = newForm->createWeakPtr();
159 #endif
160         m_form->associate(*this);
161     } else {
162 #if ENABLE(OILPAN)
163         m_form = nullptr;
164 #else
165         m_form = WeakPtr<HTMLFormElement>();
166 #endif
167     }
168     didChangeForm();
169 }
170
171 void FormAssociatedElement::willChangeForm()
172 {
173 }
174
175 void FormAssociatedElement::didChangeForm()
176 {
177 }
178
179 void FormAssociatedElement::resetFormOwner()
180 {
181     m_formWasSetByParser = false;
182     HTMLElement* element = toHTMLElement(this);
183     const AtomicString& formId(element->fastGetAttribute(formAttr));
184     HTMLFormElement* nearestForm = element->findFormAncestor();
185     // 1. If the element's form owner is not null, and either the element is not
186     // reassociateable or its form content attribute is not present, and the
187     // element's form owner is its nearest form element ancestor after the
188     // change to the ancestor chain, then do nothing, and abort these steps.
189     if (m_form && formId.isNull() && m_form.get() == nearestForm)
190         return;
191
192     HTMLFormElement* originalForm = m_form.get();
193     setForm(findAssociatedForm(element));
194     // FIXME: Move didAssociateFormControl call to didChangeForm or
195     // HTMLFormElement::associate.
196     if (m_form && m_form.get() != originalForm && m_form->inDocument())
197         element->document().didAssociateFormControl(element);
198 }
199
200 void FormAssociatedElement::formAttributeChanged()
201 {
202     resetFormOwner();
203     resetFormAttributeTargetObserver();
204 }
205
206 bool FormAssociatedElement::customError() const
207 {
208     const HTMLElement* element = toHTMLElement(this);
209     return element->willValidate() && !m_customValidationMessage.isEmpty();
210 }
211
212 bool FormAssociatedElement::hasBadInput() const
213 {
214     return false;
215 }
216
217 bool FormAssociatedElement::patternMismatch() const
218 {
219     return false;
220 }
221
222 bool FormAssociatedElement::rangeOverflow() const
223 {
224     return false;
225 }
226
227 bool FormAssociatedElement::rangeUnderflow() const
228 {
229     return false;
230 }
231
232 bool FormAssociatedElement::stepMismatch() const
233 {
234     return false;
235 }
236
237 bool FormAssociatedElement::tooLong() const
238 {
239     return false;
240 }
241
242 bool FormAssociatedElement::tooShort() const
243 {
244     return false;
245 }
246
247 bool FormAssociatedElement::typeMismatch() const
248 {
249     return false;
250 }
251
252 bool FormAssociatedElement::valid() const
253 {
254     bool someError = typeMismatch() || stepMismatch() || rangeUnderflow() || rangeOverflow()
255         || tooLong() || tooShort() || patternMismatch() || valueMissing() || hasBadInput()
256         || customError();
257     return !someError;
258 }
259
260 bool FormAssociatedElement::valueMissing() const
261 {
262     return false;
263 }
264
265 String FormAssociatedElement::customValidationMessage() const
266 {
267     return m_customValidationMessage;
268 }
269
270 String FormAssociatedElement::validationMessage() const
271 {
272     return customError() ? m_customValidationMessage : String();
273 }
274
275 void FormAssociatedElement::setCustomValidity(const String& error)
276 {
277     m_customValidationMessage = error;
278 }
279
280 void FormAssociatedElement::setFormAttributeTargetObserver(PassOwnPtrWillBeRawPtr<FormAttributeTargetObserver> newObserver)
281 {
282     if (m_formAttributeTargetObserver)
283         m_formAttributeTargetObserver->unregister();
284     m_formAttributeTargetObserver = newObserver;
285 }
286
287 void FormAssociatedElement::resetFormAttributeTargetObserver()
288 {
289     HTMLElement* element = toHTMLElement(this);
290     const AtomicString& formId(element->fastGetAttribute(formAttr));
291     if (!formId.isNull() && element->inDocument())
292         setFormAttributeTargetObserver(FormAttributeTargetObserver::create(formId, this));
293     else
294         setFormAttributeTargetObserver(nullptr);
295 }
296
297 void FormAssociatedElement::formAttributeTargetChanged()
298 {
299     resetFormOwner();
300 }
301
302 const AtomicString& FormAssociatedElement::name() const
303 {
304     const AtomicString& name = toHTMLElement(this)->getNameAttribute();
305     return name.isNull() ? emptyAtom : name;
306 }
307
308 bool FormAssociatedElement::isFormControlElementWithState() const
309 {
310     return false;
311 }
312
313 const HTMLElement& toHTMLElement(const FormAssociatedElement& associatedElement)
314 {
315     if (associatedElement.isFormControlElement())
316         return toHTMLFormControlElement(associatedElement);
317     else if (associatedElement.isLabelElement())
318         return toHTMLLabelElement(associatedElement);
319     else
320         return toHTMLObjectElement(associatedElement);
321 }
322
323 const HTMLElement* toHTMLElement(const FormAssociatedElement* associatedElement)
324 {
325     ASSERT(associatedElement);
326     return &toHTMLElement(*associatedElement);
327 }
328
329 HTMLElement* toHTMLElement(FormAssociatedElement* associatedElement)
330 {
331     return const_cast<HTMLElement*>(toHTMLElement(static_cast<const FormAssociatedElement*>(associatedElement)));
332 }
333
334 HTMLElement& toHTMLElement(FormAssociatedElement& associatedElement)
335 {
336     return const_cast<HTMLElement&>(toHTMLElement(static_cast<const FormAssociatedElement&>(associatedElement)));
337 }
338
339 PassOwnPtrWillBeRawPtr<FormAttributeTargetObserver> FormAttributeTargetObserver::create(const AtomicString& id, FormAssociatedElement* element)
340 {
341     return adoptPtrWillBeNoop(new FormAttributeTargetObserver(id, element));
342 }
343
344 FormAttributeTargetObserver::FormAttributeTargetObserver(const AtomicString& id, FormAssociatedElement* element)
345     : IdTargetObserver(toHTMLElement(element)->treeScope().idTargetObserverRegistry(), id)
346     , m_element(element)
347 {
348 }
349
350 void FormAttributeTargetObserver::trace(Visitor* visitor)
351 {
352     visitor->trace(m_element);
353     IdTargetObserver::trace(visitor);
354 }
355
356 void FormAttributeTargetObserver::idTargetChanged()
357 {
358     m_element->formAttributeTargetChanged();
359 }
360
361 } // namespace blink