OSDN Git Service

Merge WebKit at r71558: Initial merge by git.
[android-x86/external-webkit.git] / WebCore / html / HTMLFormElement.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, 2008, 2009 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 "HTMLFormElement.h"
27
28 #include "Attribute.h"
29 #include "DOMFormData.h"
30 #include "DOMWindow.h"
31 #include "Document.h"
32 #include "Event.h"
33 #include "EventNames.h"
34 #include "FileList.h"
35 #include "FileSystem.h"
36 #include "FormData.h"
37 #include "FormDataList.h"
38 #include "FormState.h"
39 #include "Frame.h"
40 #include "FrameLoader.h"
41 #include "FrameLoaderClient.h"
42 #include "HTMLDocument.h"
43 #include "HTMLFormCollection.h"
44 #include "HTMLImageElement.h"
45 #include "HTMLInputElement.h"
46 #include "HTMLNames.h"
47 #include "MIMETypeRegistry.h"
48 #include "Page.h"
49 #include "RenderTextControl.h"
50 #include "ScriptEventListener.h"
51 #include "Settings.h"
52 #include "ValidityState.h"
53 #include <limits>
54
55 #if PLATFORM(WX)
56 #include <wx/defs.h>
57 #include <wx/filename.h>
58 #endif
59
60 using namespace std;
61
62 namespace WebCore {
63
64 using namespace HTMLNames;
65
66 HTMLFormElement::HTMLFormElement(const QualifiedName& tagName, Document* document)
67     : HTMLElement(tagName, document)
68     , m_wasUserSubmitted(false)
69     , m_autocomplete(true)
70     , m_insubmit(false)
71     , m_doingsubmit(false)
72     , m_inreset(false)
73     , m_malformed(false)
74     , m_demoted(false)
75 {
76     ASSERT(hasTagName(formTag));
77 }
78
79 PassRefPtr<HTMLFormElement> HTMLFormElement::create(Document* document)
80 {
81     return adoptRef(new HTMLFormElement(formTag, document));
82 }
83
84 PassRefPtr<HTMLFormElement> HTMLFormElement::create(const QualifiedName& tagName, Document* document)
85 {
86     return adoptRef(new HTMLFormElement(tagName, document));
87 }
88
89 HTMLFormElement::~HTMLFormElement()
90 {
91     if (!m_autocomplete)
92         document()->unregisterForDocumentActivationCallbacks(this);
93
94     for (unsigned i = 0; i < m_associatedElements.size(); ++i)
95         m_associatedElements[i]->formDestroyed();
96     for (unsigned i = 0; i < m_imageElements.size(); ++i)
97         m_imageElements[i]->m_form = 0;
98 }
99
100 bool HTMLFormElement::formWouldHaveSecureSubmission(const String& url)
101 {
102     return document()->completeURL(url).protocolIs("https");
103 }
104
105 bool HTMLFormElement::rendererIsNeeded(RenderStyle* style)
106 {
107     if (!isDemoted())
108         return HTMLElement::rendererIsNeeded(style);
109
110     ContainerNode* node = parentNode();
111     RenderObject* parentRenderer = node->renderer();
112     bool parentIsTableElementPart = (parentRenderer->isTable() && node->hasTagName(tableTag))
113         || (parentRenderer->isTableRow() && node->hasTagName(trTag))
114         || (parentRenderer->isTableSection() && node->hasTagName(tbodyTag))
115         || (parentRenderer->isTableCol() && node->hasTagName(colTag))
116         || (parentRenderer->isTableCell() && node->hasTagName(trTag));
117
118     if (!parentIsTableElementPart)
119         return true;
120
121     EDisplay display = style->display();
122     bool formIsTablePart = display == TABLE || display == INLINE_TABLE || display == TABLE_ROW_GROUP
123         || display == TABLE_HEADER_GROUP || display == TABLE_FOOTER_GROUP || display == TABLE_ROW
124         || display == TABLE_COLUMN_GROUP || display == TABLE_COLUMN || display == TABLE_CELL
125         || display == TABLE_CAPTION;
126
127     return formIsTablePart;
128 }
129
130 void HTMLFormElement::insertedIntoDocument()
131 {
132     if (document()->isHTMLDocument())
133         static_cast<HTMLDocument*>(document())->addNamedItem(m_name);
134
135     HTMLElement::insertedIntoDocument();
136 }
137
138 void HTMLFormElement::removedFromDocument()
139 {
140     if (document()->isHTMLDocument())
141         static_cast<HTMLDocument*>(document())->removeNamedItem(m_name);
142
143     HTMLElement::removedFromDocument();
144 }
145
146 void HTMLFormElement::handleLocalEvents(Event* event)
147 {
148     Node* targetNode = event->target()->toNode();
149     if (event->eventPhase() != Event::CAPTURING_PHASE && targetNode && targetNode != this && (event->type() == eventNames().submitEvent || event->type() == eventNames().resetEvent)) {
150         event->stopPropagation();
151         return;
152     }
153     HTMLElement::handleLocalEvents(event);
154 }
155
156 unsigned HTMLFormElement::length() const
157 {
158     unsigned len = 0;
159     for (unsigned i = 0; i < m_associatedElements.size(); ++i)
160         if (m_associatedElements[i]->isEnumeratable())
161             ++len;
162     return len;
163 }
164
165 Node* HTMLFormElement::item(unsigned index)
166 {
167     return elements()->item(index);
168 }
169
170 void HTMLFormElement::submitImplicitly(Event* event, bool fromImplicitSubmissionTrigger)
171 {
172     int submissionTriggerCount = 0;
173     for (unsigned i = 0; i < m_associatedElements.size(); ++i) {
174         HTMLFormControlElement* formElement = m_associatedElements[i];
175         if (formElement->isSuccessfulSubmitButton()) {
176             if (formElement->renderer()) {
177                 formElement->dispatchSimulatedClick(event);
178                 return;
179             }
180         } else if (formElement->canTriggerImplicitSubmission())
181             ++submissionTriggerCount;
182     }
183     if (fromImplicitSubmissionTrigger && submissionTriggerCount == 1)
184         prepareSubmit(event);
185 }
186
187 static inline HTMLFormControlElement* submitElementFromEvent(const Event* event)
188 {
189     Node* targetNode = event->target()->toNode();
190     if (!targetNode || !targetNode->isElementNode())
191         return 0;
192     Element* targetElement = static_cast<Element*>(targetNode);
193     if (!targetElement->isFormControlElement())
194         return 0;
195     return static_cast<HTMLFormControlElement*>(targetElement);
196 }
197
198 bool HTMLFormElement::validateInteractively(Event* event)
199 {
200     ASSERT(event);
201     if (!document()->page() || !document()->page()->settings()->interactiveFormValidationEnabled() || noValidate())
202         return true;
203
204     HTMLFormControlElement* submitElement = submitElementFromEvent(event);
205     if (submitElement && submitElement->formNoValidate())
206         return true;
207
208     for (unsigned i = 0; i < m_associatedElements.size(); ++i)
209         m_associatedElements[i]->hideVisibleValidationMessage();
210
211     Vector<RefPtr<HTMLFormControlElement> > unhandledInvalidControls;
212     collectUnhandledInvalidControls(unhandledInvalidControls);
213     if (unhandledInvalidControls.isEmpty())
214         return true;
215     // If the form has invalid controls, abort submission.
216
217     RefPtr<HTMLFormElement> protector(this);
218     // Focus on the first focusable control and show a validation message.
219     for (unsigned i = 0; i < unhandledInvalidControls.size(); ++i) {
220         HTMLFormControlElement* unhandled = unhandledInvalidControls[i].get();
221         if (unhandled->isFocusable() && unhandled->inDocument()) {
222             RefPtr<Document> originalDocument(unhandled->document());
223             unhandled->scrollIntoViewIfNeeded(false);
224             // scrollIntoViewIfNeeded() dispatches events, so the state
225             // of 'unhandled' might be changed so it's no longer focusable or
226             // moved to another document.
227             if (unhandled->isFocusable() && unhandled->inDocument() && originalDocument == unhandled->document()) {
228                 unhandled->focus();
229                 unhandled->updateVisibleValidationMessage();
230                 break;
231             }
232         }
233     }
234     // Warn about all of unfocusable controls.
235     if (Frame* frame = document()->frame()) {
236         for (unsigned i = 0; i < unhandledInvalidControls.size(); ++i) {
237             HTMLFormControlElement* unhandled = unhandledInvalidControls[i].get();
238             if (unhandled->isFocusable() && unhandled->inDocument())
239                 continue;
240             String message("An invalid form control with name='%name' is not focusable.");
241             message.replace("%name", unhandled->name());
242             frame->domWindow()->console()->addMessage(HTMLMessageSource, LogMessageType, ErrorMessageLevel, message, 0, document()->url().string());
243         }
244     }
245     m_insubmit = false;
246     return false;
247 }
248
249 bool HTMLFormElement::prepareSubmit(Event* event)
250 {
251     Frame* frame = document()->frame();
252     if (m_insubmit || !frame)
253         return m_insubmit;
254
255     m_insubmit = true;
256     m_doingsubmit = false;
257
258     // Interactive validation must be done before dispatching the submit event.
259     if (!validateInteractively(event))
260         return false;
261
262     frame->loader()->client()->dispatchWillSendSubmitEvent(this);
263
264     if (dispatchEvent(Event::create(eventNames().submitEvent, true, true)) && !m_doingsubmit)
265         m_doingsubmit = true;
266
267     m_insubmit = false;
268
269     if (m_doingsubmit)
270         submit(event, true, true, NotSubmittedByJavaScript);
271
272     return m_doingsubmit;
273 }
274
275 void HTMLFormElement::submit(Frame* javaScriptActiveFrame)
276 {
277     if (javaScriptActiveFrame)
278         submit(0, false, javaScriptActiveFrame->script()->anyPageIsProcessingUserGesture(), SubmittedByJavaScript);
279     else
280         submit(0, false, true, NotSubmittedByJavaScript);
281 }
282
283 void HTMLFormElement::submit(Event* event, bool activateSubmitButton, bool processingUserGesture, FormSubmissionTrigger formSubmissionTrigger)
284 {
285     FrameView* view = document()->view();
286     Frame* frame = document()->frame();
287     if (!view || !frame)
288         return;
289
290     if (m_insubmit) {
291         m_doingsubmit = true;
292         return;
293     }
294
295     m_insubmit = true;
296     m_wasUserSubmitted = processingUserGesture;
297
298     HTMLFormControlElement* firstSuccessfulSubmitButton = 0;
299     bool needButtonActivation = activateSubmitButton; // do we need to activate a submit button?
300
301     for (unsigned i = 0; i < m_associatedElements.size(); ++i) {
302         HTMLFormControlElement* control = m_associatedElements[i];
303         if (needButtonActivation) {
304             if (control->isActivatedSubmit())
305                 needButtonActivation = false;
306             else if (firstSuccessfulSubmitButton == 0 && control->isSuccessfulSubmitButton())
307                 firstSuccessfulSubmitButton = control;
308         }
309     }
310
311     if (needButtonActivation && firstSuccessfulSubmitButton)
312         firstSuccessfulSubmitButton->setActivatedSubmit(true);
313
314     frame->loader()->submitForm(FormSubmission::create(this, m_attributes, event, !processingUserGesture, formSubmissionTrigger));
315
316     if (needButtonActivation && firstSuccessfulSubmitButton)
317         firstSuccessfulSubmitButton->setActivatedSubmit(false);
318
319     m_doingsubmit = m_insubmit = false;
320 }
321
322 void HTMLFormElement::reset()
323 {
324     Frame* frame = document()->frame();
325     if (m_inreset || !frame)
326         return;
327
328     m_inreset = true;
329
330     // ### DOM2 labels this event as not cancelable, however
331     // common browsers( sick! ) allow it be cancelled.
332     if (!dispatchEvent(Event::create(eventNames().resetEvent, true, true))) {
333         m_inreset = false;
334         return;
335     }
336
337     for (unsigned i = 0; i < m_associatedElements.size(); ++i)
338         m_associatedElements[i]->reset();
339
340     m_inreset = false;
341 }
342
343 void HTMLFormElement::parseMappedAttribute(Attribute* attr)
344 {
345     if (attr->name() == actionAttr)
346         m_attributes.parseAction(attr->value());
347     else if (attr->name() == targetAttr)
348         m_attributes.setTarget(attr->value());
349     else if (attr->name() == methodAttr)
350         m_attributes.parseMethodType(attr->value());
351     else if (attr->name() == enctypeAttr)
352         m_attributes.parseEncodingType(attr->value());
353     else if (attr->name() == accept_charsetAttr)
354         // space separated list of charsets the server
355         // accepts - see rfc2045
356         m_attributes.setAcceptCharset(attr->value());
357     else if (attr->name() == acceptAttr) {
358         // ignore this one for the moment...
359     } else if (attr->name() == autocompleteAttr) {
360         m_autocomplete = !equalIgnoringCase(attr->value(), "off");
361         if (!m_autocomplete)
362             document()->registerForDocumentActivationCallbacks(this);
363         else
364             document()->unregisterForDocumentActivationCallbacks(this);
365     } else if (attr->name() == onsubmitAttr)
366         setAttributeEventListener(eventNames().submitEvent, createAttributeEventListener(this, attr));
367     else if (attr->name() == onresetAttr)
368         setAttributeEventListener(eventNames().resetEvent, createAttributeEventListener(this, attr));
369     else if (attr->name() == nameAttr) {
370         const AtomicString& newName = attr->value();
371         if (inDocument() && document()->isHTMLDocument()) {
372             HTMLDocument* document = static_cast<HTMLDocument*>(this->document());
373             document->removeNamedItem(m_name);
374             document->addNamedItem(newName);
375         }
376         m_name = newName;
377     } else
378         HTMLElement::parseMappedAttribute(attr);
379 }
380
381 template<class T, size_t n> static void removeFromVector(Vector<T*, n> & vec, T* item)
382 {
383     size_t size = vec.size();
384     for (size_t i = 0; i != size; ++i)
385         if (vec[i] == item) {
386             vec.remove(i);
387             break;
388         }
389 }
390
391 unsigned HTMLFormElement::formElementIndex(HTMLFormControlElement* e)
392 {
393     // Check for the special case where this element is the very last thing in
394     // the form's tree of children; we don't want to walk the entire tree in that
395     // common case that occurs during parsing; instead we'll just return a value
396     // that says "add this form element to the end of the array".
397     if (e->traverseNextNode(this)) {
398         unsigned i = 0;
399         for (Node* node = this; node; node = node->traverseNextNode(this)) {
400             if (node == e)
401                 return i;
402             if (node->isHTMLElement()
403                     && static_cast<Element*>(node)->isFormControlElement()
404                     && static_cast<HTMLFormControlElement*>(node)->form() == this)
405                 ++i;
406         }
407     }
408     return m_associatedElements.size();
409 }
410
411 void HTMLFormElement::registerFormElement(HTMLFormControlElement* e)
412 {
413     document()->checkedRadioButtons().removeButton(e);
414     m_checkedRadioButtons.addButton(e);
415     m_associatedElements.insert(formElementIndex(e), e);
416 }
417
418 void HTMLFormElement::removeFormElement(HTMLFormControlElement* e)
419 {
420     m_checkedRadioButtons.removeButton(e);
421     removeFromVector(m_associatedElements, e);
422 }
423
424 bool HTMLFormElement::isURLAttribute(Attribute* attr) const
425 {
426     return attr->name() == actionAttr;
427 }
428
429 void HTMLFormElement::registerImgElement(HTMLImageElement* e)
430 {
431     ASSERT(m_imageElements.find(e) == notFound);
432     m_imageElements.append(e);
433 }
434
435 void HTMLFormElement::removeImgElement(HTMLImageElement* e)
436 {
437     ASSERT(m_imageElements.find(e) != notFound);
438     removeFromVector(m_imageElements, e);
439 }
440
441 PassRefPtr<HTMLCollection> HTMLFormElement::elements()
442 {
443     return HTMLFormCollection::create(this);
444 }
445
446 String HTMLFormElement::name() const
447 {
448     return getAttribute(nameAttr);
449 }
450
451 bool HTMLFormElement::noValidate() const
452 {
453     return !getAttribute(novalidateAttr).isNull();
454 }
455
456 // FIXME: This function should be removed because it does not do the same thing as the
457 // JavaScript binding for action, which treats action as a URL attribute. Last time I
458 // (Darin Adler) removed this, someone added it back, so I am leaving it in for now.
459 String HTMLFormElement::action() const
460 {
461     return getAttribute(actionAttr);
462 }
463
464 void HTMLFormElement::setAction(const String &value)
465 {
466     setAttribute(actionAttr, value);
467 }
468
469 void HTMLFormElement::setEnctype(const String &value)
470 {
471     setAttribute(enctypeAttr, value);
472 }
473
474 String HTMLFormElement::method() const
475 {
476     return getAttribute(methodAttr);
477 }
478
479 void HTMLFormElement::setMethod(const String &value)
480 {
481     setAttribute(methodAttr, value);
482 }
483
484 String HTMLFormElement::target() const
485 {
486     return getAttribute(targetAttr);
487 }
488
489 bool HTMLFormElement::wasUserSubmitted() const
490 {
491     return m_wasUserSubmitted;
492 }
493
494 HTMLFormControlElement* HTMLFormElement::defaultButton() const
495 {
496     for (unsigned i = 0; i < m_associatedElements.size(); ++i) {
497         HTMLFormControlElement* control = m_associatedElements[i];
498         if (control->isSuccessfulSubmitButton())
499             return control;
500     }
501
502     return 0;
503 }
504
505 bool HTMLFormElement::checkValidity()
506 {
507     Vector<RefPtr<HTMLFormControlElement> > controls;
508     collectUnhandledInvalidControls(controls);
509     return controls.isEmpty();
510 }
511
512 void HTMLFormElement::collectUnhandledInvalidControls(Vector<RefPtr<HTMLFormControlElement> >& unhandledInvalidControls)
513 {
514     RefPtr<HTMLFormElement> protector(this);
515     // Copy m_associatedElements because event handlers called from
516     // HTMLFormControlElement::checkValidity() might change m_associatedElements.
517     Vector<RefPtr<HTMLFormControlElement> > elements;
518     elements.reserveCapacity(m_associatedElements.size());
519     for (unsigned i = 0; i < m_associatedElements.size(); ++i)
520         elements.append(m_associatedElements[i]);
521     for (unsigned i = 0; i < elements.size(); ++i) {
522         if (elements[i]->form() == this)
523             elements[i]->checkValidity(&unhandledInvalidControls);
524     }
525 }
526
527 PassRefPtr<HTMLFormControlElement> HTMLFormElement::elementForAlias(const AtomicString& alias)
528 {
529     if (alias.isEmpty() || !m_elementAliases)
530         return 0;
531     return m_elementAliases->get(alias.impl());
532 }
533
534 void HTMLFormElement::addElementAlias(HTMLFormControlElement* element, const AtomicString& alias)
535 {
536     if (alias.isEmpty())
537         return;
538     if (!m_elementAliases)
539         m_elementAliases = adoptPtr(new AliasMap);
540     m_elementAliases->set(alias.impl(), element);
541 }
542
543 void HTMLFormElement::getNamedElements(const AtomicString& name, Vector<RefPtr<Node> >& namedItems)
544 {
545     elements()->namedItems(name, namedItems);
546
547     // see if we have seen something with this name before
548     RefPtr<HTMLFormControlElement> aliasElem;
549     if ((aliasElem = elementForAlias(name))) {
550         bool found = false;
551         for (unsigned n = 0; n < namedItems.size(); n++) {
552             if (namedItems[n] == aliasElem.get()) {
553                 found = true;
554                 break;
555             }
556         }
557         if (!found)
558             // we have seen it before but it is gone now. still, we need to return it.
559             namedItems.append(aliasElem.get());
560     }
561     // name has been accessed, remember it
562     if (namedItems.size() && aliasElem != namedItems.first())
563         addElementAlias(static_cast<HTMLFormControlElement*>(namedItems.first().get()), name);
564 }
565
566 void HTMLFormElement::documentDidBecomeActive()
567 {
568     ASSERT(!m_autocomplete);
569
570     for (unsigned i = 0; i < m_associatedElements.size(); ++i)
571         m_associatedElements[i]->reset();
572 }
573
574 void HTMLFormElement::willMoveToNewOwnerDocument()
575 {
576     if (!m_autocomplete)
577         document()->unregisterForDocumentActivationCallbacks(this);
578     HTMLElement::willMoveToNewOwnerDocument();
579 }
580
581 void HTMLFormElement::didMoveToNewOwnerDocument()
582 {
583     if (!m_autocomplete)
584         document()->registerForDocumentActivationCallbacks(this);
585     HTMLElement::didMoveToNewOwnerDocument();
586 }
587
588 } // namespace