| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
| 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) | 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) |
| 4 * (C) 2001 Dirk Mueller (mueller@kde.org) | 4 * (C) 2001 Dirk Mueller (mueller@kde.org) |
| 5 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserv
ed. | 5 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserv
ed. |
| 6 * (C) 2006 Alexey Proskuryakov (ap@nypop.com) | 6 * (C) 2006 Alexey Proskuryakov (ap@nypop.com) |
| 7 * | 7 * |
| 8 * This library is free software; you can redistribute it and/or | 8 * This library is free software; you can redistribute it and/or |
| 9 * modify it under the terms of the GNU Library General Public | 9 * modify it under the terms of the GNU Library General Public |
| 10 * License as published by the Free Software Foundation; either | 10 * License as published by the Free Software Foundation; either |
| (...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 266 // FIXME: Consolidate this and similar code in FormSubmission.cpp. | 266 // FIXME: Consolidate this and similar code in FormSubmission.cpp. |
| 267 static inline HTMLFormControlElement* submitElementFromEvent(const Event* event) | 267 static inline HTMLFormControlElement* submitElementFromEvent(const Event* event) |
| 268 { | 268 { |
| 269 for (Node* node = event->target()->toNode(); node; node = node->parentOrShad
owHostNode()) { | 269 for (Node* node = event->target()->toNode(); node; node = node->parentOrShad
owHostNode()) { |
| 270 if (node->isElementNode() && toElement(node)->isFormControlElement()) | 270 if (node->isElementNode() && toElement(node)->isFormControlElement()) |
| 271 return toHTMLFormControlElement(node); | 271 return toHTMLFormControlElement(node); |
| 272 } | 272 } |
| 273 return 0; | 273 return 0; |
| 274 } | 274 } |
| 275 | 275 |
| 276 bool HTMLFormElement::validateInteractively(Event* event) | 276 bool HTMLFormElement::validateInteractively() |
| 277 { | 277 { |
| 278 ASSERT(event); | |
| 279 if (!document().page() || noValidate()) | |
| 280 return true; | |
| 281 | |
| 282 HTMLFormControlElement* submitElement = submitElementFromEvent(event); | |
| 283 if (submitElement && submitElement->formNoValidate()) | |
| 284 return true; | |
| 285 | |
| 286 const FormAssociatedElement::List& elements = associatedElements(); | 278 const FormAssociatedElement::List& elements = associatedElements(); |
| 287 for (unsigned i = 0; i < elements.size(); ++i) { | 279 for (unsigned i = 0; i < elements.size(); ++i) { |
| 288 if (elements[i]->isFormControlElement()) | 280 if (elements[i]->isFormControlElement()) |
| 289 toHTMLFormControlElement(elements[i])->hideVisibleValidationMessage(
); | 281 toHTMLFormControlElement(elements[i])->hideVisibleValidationMessage(
); |
| 290 } | 282 } |
| 291 | 283 |
| 292 WillBeHeapVector<RefPtrWillBeMember<FormAssociatedElement> > unhandledInvali
dControls; | 284 WillBeHeapVector<RefPtrWillBeMember<HTMLFormControlElement> > unhandledInval
idControls; |
| 293 if (!checkInvalidControlsAndCollectUnhandled(&unhandledInvalidControls, Chec
kValidityDispatchInvalidEvent)) | 285 if (!checkInvalidControlsAndCollectUnhandled(&unhandledInvalidControls, Chec
kValidityDispatchInvalidEvent)) |
| 294 return true; | 286 return true; |
| 295 // Because the form has invalid controls, we abort the form submission and | 287 // Because the form has invalid controls, we abort the form submission and |
| 296 // show a validation message on a focusable form control. | 288 // show a validation message on a focusable form control. |
| 297 | 289 |
| 298 // Needs to update layout now because we'd like to call isFocusable(), which | 290 // Needs to update layout now because we'd like to call isFocusable(), which |
| 299 // has !renderer()->needsLayout() assertion. | 291 // has !renderer()->needsLayout() assertion. |
| 300 document().updateLayoutIgnorePendingStylesheets(); | 292 document().updateLayoutIgnorePendingStylesheets(); |
| 301 | 293 |
| 302 RefPtrWillBeRawPtr<HTMLFormElement> protector(this); | 294 RefPtrWillBeRawPtr<HTMLFormElement> protector(this); |
| 303 // Focus on the first focusable control and show a validation message. | 295 // Focus on the first focusable control and show a validation message. |
| 304 for (unsigned i = 0; i < unhandledInvalidControls.size(); ++i) { | 296 for (unsigned i = 0; i < unhandledInvalidControls.size(); ++i) { |
| 305 FormAssociatedElement* unhandledAssociatedElement = unhandledInvalidCont
rols[i].get(); | 297 HTMLFormControlElement* unhandled = unhandledInvalidControls[i].get(); |
| 306 HTMLElement* unhandled = toHTMLElement(unhandledAssociatedElement); | 298 if (unhandled->bringAttentionToInvalidElement()) |
| 307 if (unhandled->isFocusable() && unhandled->inDocument()) { | |
| 308 unhandled->scrollIntoViewIfNeeded(false); | |
| 309 unhandled->focus(); | |
| 310 if (unhandled->isFormControlElement()) | |
| 311 toHTMLFormControlElement(unhandled)->updateVisibleValidationMess
age(); | |
| 312 break; | 299 break; |
| 313 } | |
| 314 } | 300 } |
| 315 // Warn about all of unfocusable controls. | 301 // Warn about all of unfocusable controls. |
| 316 if (document().frame()) { | 302 if (document().frame()) { |
| 317 for (unsigned i = 0; i < unhandledInvalidControls.size(); ++i) { | 303 for (unsigned i = 0; i < unhandledInvalidControls.size(); ++i) { |
| 318 FormAssociatedElement* unhandledAssociatedElement = unhandledInvalid
Controls[i].get(); | 304 HTMLFormControlElement* unhandled = unhandledInvalidControls[i].get(
); |
| 319 HTMLElement* unhandled = toHTMLElement(unhandledAssociatedElement); | |
| 320 if (unhandled->isFocusable() && unhandled->inDocument()) | 305 if (unhandled->isFocusable() && unhandled->inDocument()) |
| 321 continue; | 306 continue; |
| 322 String message("An invalid form control with name='%name' is not foc
usable."); | 307 String message("An invalid form control with name='%name' is not foc
usable."); |
| 323 message.replace("%name", unhandledAssociatedElement->name()); | 308 message.replace("%name", unhandled->name()); |
| 324 document().addConsoleMessage(ConsoleMessage::create(RenderingMessage
Source, ErrorMessageLevel, message)); | 309 document().addConsoleMessage(ConsoleMessage::create(RenderingMessage
Source, ErrorMessageLevel, message)); |
| 325 } | 310 } |
| 326 } | 311 } |
| 327 return false; | 312 return false; |
| 328 } | 313 } |
| 329 | 314 |
| 330 void HTMLFormElement::prepareForSubmission(Event* event) | 315 void HTMLFormElement::prepareForSubmission(Event* event) |
| 331 { | 316 { |
| 332 RefPtrWillBeRawPtr<HTMLFormElement> protector(this); | 317 RefPtrWillBeRawPtr<HTMLFormElement> protector(this); |
| 333 LocalFrame* frame = document().frame(); | 318 LocalFrame* frame = document().frame(); |
| 334 if (!frame || m_isSubmittingOrInUserJSSubmitEvent) | 319 if (!frame || m_isSubmittingOrInUserJSSubmitEvent) |
| 335 return; | 320 return; |
| 336 | 321 |
| 322 bool skipValidation = !document().page() || noValidate(); |
| 323 ASSERT(event); |
| 324 HTMLFormControlElement* submitElement = submitElementFromEvent(event); |
| 325 if (submitElement && submitElement->formNoValidate()) |
| 326 skipValidation = true; |
| 327 |
| 337 // Interactive validation must be done before dispatching the submit event. | 328 // Interactive validation must be done before dispatching the submit event. |
| 338 if (!validateInteractively(event)) | 329 if (!skipValidation && !validateInteractively()) |
| 339 return; | 330 return; |
| 340 | 331 |
| 341 m_isSubmittingOrInUserJSSubmitEvent = true; | 332 m_isSubmittingOrInUserJSSubmitEvent = true; |
| 342 m_shouldSubmit = false; | 333 m_shouldSubmit = false; |
| 343 | 334 |
| 344 frame->loader().client()->dispatchWillSendSubmitEvent(this); | 335 frame->loader().client()->dispatchWillSendSubmitEvent(this); |
| 345 | 336 |
| 346 if (dispatchEvent(Event::createCancelableBubble(EventTypeNames::submit))) | 337 if (dispatchEvent(Event::createCancelableBubble(EventTypeNames::submit))) |
| 347 m_shouldSubmit = true; | 338 m_shouldSubmit = true; |
| 348 | 339 |
| (...skipping 380 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 729 // validity recalculation. In the near future, implement validity cache and | 720 // validity recalculation. In the near future, implement validity cache and |
| 730 // recalculate style only if it changed. | 721 // recalculate style only if it changed. |
| 731 setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::createW
ithExtraData(StyleChangeReason::PseudoClass, StyleChangeExtraData::Invalid)); | 722 setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::createW
ithExtraData(StyleChangeReason::PseudoClass, StyleChangeExtraData::Invalid)); |
| 732 } | 723 } |
| 733 | 724 |
| 734 bool HTMLFormElement::checkValidity() | 725 bool HTMLFormElement::checkValidity() |
| 735 { | 726 { |
| 736 return !checkInvalidControlsAndCollectUnhandled(0, CheckValidityDispatchInva
lidEvent); | 727 return !checkInvalidControlsAndCollectUnhandled(0, CheckValidityDispatchInva
lidEvent); |
| 737 } | 728 } |
| 738 | 729 |
| 739 bool HTMLFormElement::checkInvalidControlsAndCollectUnhandled(WillBeHeapVector<R
efPtrWillBeMember<FormAssociatedElement> >* unhandledInvalidControls, CheckValid
ityEventBehavior eventBehavior) | 730 bool HTMLFormElement::checkInvalidControlsAndCollectUnhandled(WillBeHeapVector<R
efPtrWillBeMember<HTMLFormControlElement> >* unhandledInvalidControls, CheckVali
dityEventBehavior eventBehavior) |
| 740 { | 731 { |
| 741 RefPtrWillBeRawPtr<HTMLFormElement> protector(this); | 732 RefPtrWillBeRawPtr<HTMLFormElement> protector(this); |
| 742 // Copy associatedElements because event handlers called from | 733 // Copy associatedElements because event handlers called from |
| 743 // HTMLFormControlElement::checkValidity() might change associatedElements. | 734 // HTMLFormControlElement::checkValidity() might change associatedElements. |
| 744 const FormAssociatedElement::List& associatedElements = this->associatedElem
ents(); | 735 const FormAssociatedElement::List& associatedElements = this->associatedElem
ents(); |
| 745 WillBeHeapVector<RefPtrWillBeMember<FormAssociatedElement> > elements; | 736 WillBeHeapVector<RefPtrWillBeMember<FormAssociatedElement> > elements; |
| 746 elements.reserveCapacity(associatedElements.size()); | 737 elements.reserveCapacity(associatedElements.size()); |
| 747 for (unsigned i = 0; i < associatedElements.size(); ++i) | 738 for (unsigned i = 0; i < associatedElements.size(); ++i) |
| 748 elements.append(associatedElements[i]); | 739 elements.append(associatedElements[i]); |
| 749 bool hasInvalidControls = false; | 740 bool hasInvalidControls = false; |
| 750 for (unsigned i = 0; i < elements.size(); ++i) { | 741 for (unsigned i = 0; i < elements.size(); ++i) { |
| 751 if (elements[i]->form() == this && elements[i]->isFormControlElement())
{ | 742 if (elements[i]->form() == this && elements[i]->isFormControlElement())
{ |
| 752 HTMLFormControlElement* control = toHTMLFormControlElement(elements[
i].get()); | 743 HTMLFormControlElement* control = toHTMLFormControlElement(elements[
i].get()); |
| 753 if (!control->checkValidity(unhandledInvalidControls, eventBehavior)
&& control->formOwner() == this) | 744 if (!control->checkValidity(unhandledInvalidControls, eventBehavior)
&& control->formOwner() == this) |
| 754 hasInvalidControls = true; | 745 hasInvalidControls = true; |
| 755 } | 746 } |
| 756 } | 747 } |
| 757 return hasInvalidControls; | 748 return hasInvalidControls; |
| 758 } | 749 } |
| 759 | 750 |
| 751 bool HTMLFormElement::reportValidity() |
| 752 { |
| 753 return validateInteractively(); |
| 754 } |
| 755 |
| 760 Element* HTMLFormElement::elementFromPastNamesMap(const AtomicString& pastName) | 756 Element* HTMLFormElement::elementFromPastNamesMap(const AtomicString& pastName) |
| 761 { | 757 { |
| 762 if (pastName.isEmpty() || !m_pastNamesMap) | 758 if (pastName.isEmpty() || !m_pastNamesMap) |
| 763 return 0; | 759 return 0; |
| 764 Element* element = m_pastNamesMap->get(pastName); | 760 Element* element = m_pastNamesMap->get(pastName); |
| 765 #if ENABLE(ASSERT) | 761 #if ENABLE(ASSERT) |
| 766 if (!element) | 762 if (!element) |
| 767 return 0; | 763 return 0; |
| 768 ASSERT_WITH_SECURITY_IMPLICATION(toHTMLElement(element)->formOwner() == this
); | 764 ASSERT_WITH_SECURITY_IMPLICATION(toHTMLElement(element)->formOwner() == this
); |
| 769 if (isHTMLImageElement(*element)) { | 765 if (isHTMLImageElement(*element)) { |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 859 } | 855 } |
| 860 | 856 |
| 861 void HTMLFormElement::setDemoted(bool demoted) | 857 void HTMLFormElement::setDemoted(bool demoted) |
| 862 { | 858 { |
| 863 if (demoted) | 859 if (demoted) |
| 864 UseCounter::count(document(), UseCounter::DemotedFormElement); | 860 UseCounter::count(document(), UseCounter::DemotedFormElement); |
| 865 m_wasDemoted = demoted; | 861 m_wasDemoted = demoted; |
| 866 } | 862 } |
| 867 | 863 |
| 868 } // namespace | 864 } // namespace |
| OLD | NEW |