| 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->isFocusable()) { |
| 307 if (unhandled->isFocusable() && unhandled->inDocument()) { | 299 unhandled->showValidationMessage(); |
| 308 unhandled->scrollIntoViewIfNeeded(false); | |
| 309 unhandled->focus(); | |
| 310 if (unhandled->isFormControlElement()) | |
| 311 toHTMLFormControlElement(unhandled)->updateVisibleValidationMess
age(); | |
| 312 break; | 300 break; |
| 313 } | 301 } |
| 314 } | 302 } |
| 315 // Warn about all of unfocusable controls. | 303 // Warn about all of unfocusable controls. |
| 316 if (document().frame()) { | 304 if (document().frame()) { |
| 317 for (unsigned i = 0; i < unhandledInvalidControls.size(); ++i) { | 305 for (unsigned i = 0; i < unhandledInvalidControls.size(); ++i) { |
| 318 FormAssociatedElement* unhandledAssociatedElement = unhandledInvalid
Controls[i].get(); | 306 HTMLFormControlElement* unhandled = unhandledInvalidControls[i].get(
); |
| 319 HTMLElement* unhandled = toHTMLElement(unhandledAssociatedElement); | 307 if (unhandled->isFocusable()) |
| 320 if (unhandled->isFocusable() && unhandled->inDocument()) | |
| 321 continue; | 308 continue; |
| 322 String message("An invalid form control with name='%name' is not foc
usable."); | 309 String message("An invalid form control with name='%name' is not foc
usable."); |
| 323 message.replace("%name", unhandledAssociatedElement->name()); | 310 message.replace("%name", unhandled->name()); |
| 324 document().addConsoleMessage(ConsoleMessage::create(RenderingMessage
Source, ErrorMessageLevel, message)); | 311 document().addConsoleMessage(ConsoleMessage::create(RenderingMessage
Source, ErrorMessageLevel, message)); |
| 325 } | 312 } |
| 326 } | 313 } |
| 327 return false; | 314 return false; |
| 328 } | 315 } |
| 329 | 316 |
| 330 void HTMLFormElement::prepareForSubmission(Event* event) | 317 void HTMLFormElement::prepareForSubmission(Event* event) |
| 331 { | 318 { |
| 332 RefPtrWillBeRawPtr<HTMLFormElement> protector(this); | 319 RefPtrWillBeRawPtr<HTMLFormElement> protector(this); |
| 333 LocalFrame* frame = document().frame(); | 320 LocalFrame* frame = document().frame(); |
| 334 if (!frame || m_isSubmittingOrInUserJSSubmitEvent) | 321 if (!frame || m_isSubmittingOrInUserJSSubmitEvent) |
| 335 return; | 322 return; |
| 336 | 323 |
| 324 bool skipValidation = !document().page() || noValidate(); |
| 325 ASSERT(event); |
| 326 HTMLFormControlElement* submitElement = submitElementFromEvent(event); |
| 327 if (submitElement && submitElement->formNoValidate()) |
| 328 skipValidation = true; |
| 329 |
| 337 // Interactive validation must be done before dispatching the submit event. | 330 // Interactive validation must be done before dispatching the submit event. |
| 338 if (!validateInteractively(event)) | 331 if (!skipValidation && !validateInteractively()) |
| 339 return; | 332 return; |
| 340 | 333 |
| 341 m_isSubmittingOrInUserJSSubmitEvent = true; | 334 m_isSubmittingOrInUserJSSubmitEvent = true; |
| 342 m_shouldSubmit = false; | 335 m_shouldSubmit = false; |
| 343 | 336 |
| 344 frame->loader().client()->dispatchWillSendSubmitEvent(this); | 337 frame->loader().client()->dispatchWillSendSubmitEvent(this); |
| 345 | 338 |
| 346 if (dispatchEvent(Event::createCancelableBubble(EventTypeNames::submit))) | 339 if (dispatchEvent(Event::createCancelableBubble(EventTypeNames::submit))) |
| 347 m_shouldSubmit = true; | 340 m_shouldSubmit = true; |
| 348 | 341 |
| (...skipping 380 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 729 // validity recalculation. In the near future, implement validity cache and | 722 // validity recalculation. In the near future, implement validity cache and |
| 730 // recalculate style only if it changed. | 723 // recalculate style only if it changed. |
| 731 setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::createW
ithExtraData(StyleChangeReason::PseudoClass, StyleChangeExtraData::Invalid)); | 724 setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::createW
ithExtraData(StyleChangeReason::PseudoClass, StyleChangeExtraData::Invalid)); |
| 732 } | 725 } |
| 733 | 726 |
| 734 bool HTMLFormElement::checkValidity() | 727 bool HTMLFormElement::checkValidity() |
| 735 { | 728 { |
| 736 return !checkInvalidControlsAndCollectUnhandled(0, CheckValidityDispatchInva
lidEvent); | 729 return !checkInvalidControlsAndCollectUnhandled(0, CheckValidityDispatchInva
lidEvent); |
| 737 } | 730 } |
| 738 | 731 |
| 739 bool HTMLFormElement::checkInvalidControlsAndCollectUnhandled(WillBeHeapVector<R
efPtrWillBeMember<FormAssociatedElement> >* unhandledInvalidControls, CheckValid
ityEventBehavior eventBehavior) | 732 bool HTMLFormElement::checkInvalidControlsAndCollectUnhandled(WillBeHeapVector<R
efPtrWillBeMember<HTMLFormControlElement> >* unhandledInvalidControls, CheckVali
dityEventBehavior eventBehavior) |
| 740 { | 733 { |
| 741 RefPtrWillBeRawPtr<HTMLFormElement> protector(this); | 734 RefPtrWillBeRawPtr<HTMLFormElement> protector(this); |
| 742 // Copy associatedElements because event handlers called from | 735 // Copy associatedElements because event handlers called from |
| 743 // HTMLFormControlElement::checkValidity() might change associatedElements. | 736 // HTMLFormControlElement::checkValidity() might change associatedElements. |
| 744 const FormAssociatedElement::List& associatedElements = this->associatedElem
ents(); | 737 const FormAssociatedElement::List& associatedElements = this->associatedElem
ents(); |
| 745 WillBeHeapVector<RefPtrWillBeMember<FormAssociatedElement> > elements; | 738 WillBeHeapVector<RefPtrWillBeMember<FormAssociatedElement> > elements; |
| 746 elements.reserveCapacity(associatedElements.size()); | 739 elements.reserveCapacity(associatedElements.size()); |
| 747 for (unsigned i = 0; i < associatedElements.size(); ++i) | 740 for (unsigned i = 0; i < associatedElements.size(); ++i) |
| 748 elements.append(associatedElements[i]); | 741 elements.append(associatedElements[i]); |
| 749 bool hasInvalidControls = false; | 742 bool hasInvalidControls = false; |
| 750 for (unsigned i = 0; i < elements.size(); ++i) { | 743 for (unsigned i = 0; i < elements.size(); ++i) { |
| 751 if (elements[i]->form() == this && elements[i]->isFormControlElement())
{ | 744 if (elements[i]->form() == this && elements[i]->isFormControlElement())
{ |
| 752 HTMLFormControlElement* control = toHTMLFormControlElement(elements[
i].get()); | 745 HTMLFormControlElement* control = toHTMLFormControlElement(elements[
i].get()); |
| 753 if (!control->checkValidity(unhandledInvalidControls, eventBehavior)
&& control->formOwner() == this) | 746 if (!control->checkValidity(unhandledInvalidControls, eventBehavior)
&& control->formOwner() == this) |
| 754 hasInvalidControls = true; | 747 hasInvalidControls = true; |
| 755 } | 748 } |
| 756 } | 749 } |
| 757 return hasInvalidControls; | 750 return hasInvalidControls; |
| 758 } | 751 } |
| 759 | 752 |
| 753 bool HTMLFormElement::reportValidity() |
| 754 { |
| 755 return validateInteractively(); |
| 756 } |
| 757 |
| 760 Element* HTMLFormElement::elementFromPastNamesMap(const AtomicString& pastName) | 758 Element* HTMLFormElement::elementFromPastNamesMap(const AtomicString& pastName) |
| 761 { | 759 { |
| 762 if (pastName.isEmpty() || !m_pastNamesMap) | 760 if (pastName.isEmpty() || !m_pastNamesMap) |
| 763 return 0; | 761 return 0; |
| 764 Element* element = m_pastNamesMap->get(pastName); | 762 Element* element = m_pastNamesMap->get(pastName); |
| 765 #if ENABLE(ASSERT) | 763 #if ENABLE(ASSERT) |
| 766 if (!element) | 764 if (!element) |
| 767 return 0; | 765 return 0; |
| 768 ASSERT_WITH_SECURITY_IMPLICATION(toHTMLElement(element)->formOwner() == this
); | 766 ASSERT_WITH_SECURITY_IMPLICATION(toHTMLElement(element)->formOwner() == this
); |
| 769 if (isHTMLImageElement(*element)) { | 767 if (isHTMLImageElement(*element)) { |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 859 } | 857 } |
| 860 | 858 |
| 861 void HTMLFormElement::setDemoted(bool demoted) | 859 void HTMLFormElement::setDemoted(bool demoted) |
| 862 { | 860 { |
| 863 if (demoted) | 861 if (demoted) |
| 864 UseCounter::count(document(), UseCounter::DemotedFormElement); | 862 UseCounter::count(document(), UseCounter::DemotedFormElement); |
| 865 m_wasDemoted = demoted; | 863 m_wasDemoted = demoted; |
| 866 } | 864 } |
| 867 | 865 |
| 868 } // namespace | 866 } // namespace |
| OLD | NEW |