| 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 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 227 } | 227 } |
| 228 if (fromImplicitSubmissionTrigger) { | 228 if (fromImplicitSubmissionTrigger) { |
| 229 // Default (submit) button is not activated; no implicit submiss
ion. | 229 // Default (submit) button is not activated; no implicit submiss
ion. |
| 230 return; | 230 return; |
| 231 } | 231 } |
| 232 } else if (control->canTriggerImplicitSubmission()) { | 232 } else if (control->canTriggerImplicitSubmission()) { |
| 233 ++submissionTriggerCount; | 233 ++submissionTriggerCount; |
| 234 } | 234 } |
| 235 } | 235 } |
| 236 if (fromImplicitSubmissionTrigger && submissionTriggerCount == 1) | 236 if (fromImplicitSubmissionTrigger && submissionTriggerCount == 1) |
| 237 prepareForSubmission(event); | 237 prepareForSubmission(event, nullptr); |
| 238 } | |
| 239 | |
| 240 // FIXME: Consolidate this and similar code in FormSubmission.cpp. | |
| 241 static inline HTMLFormControlElement* submitElementFromEvent(const Event* event) | |
| 242 { | |
| 243 for (Node* node = event->target()->toNode(); node; node = node->parentOrShad
owHostNode()) { | |
| 244 if (node->isElementNode() && toElement(node)->isFormControlElement()) | |
| 245 return toHTMLFormControlElement(node); | |
| 246 } | |
| 247 return 0; | |
| 248 } | 238 } |
| 249 | 239 |
| 250 bool HTMLFormElement::validateInteractively() | 240 bool HTMLFormElement::validateInteractively() |
| 251 { | 241 { |
| 252 UseCounter::count(document(), UseCounter::FormValidationStarted); | 242 UseCounter::count(document(), UseCounter::FormValidationStarted); |
| 253 const FormAssociatedElement::List& elements = associatedElements(); | 243 const FormAssociatedElement::List& elements = associatedElements(); |
| 254 for (unsigned i = 0; i < elements.size(); ++i) { | 244 for (unsigned i = 0; i < elements.size(); ++i) { |
| 255 if (elements[i]->isFormControlElement()) | 245 if (elements[i]->isFormControlElement()) |
| 256 toHTMLFormControlElement(elements[i])->hideVisibleValidationMessage(
); | 246 toHTMLFormControlElement(elements[i])->hideVisibleValidationMessage(
); |
| 257 } | 247 } |
| (...skipping 25 matching lines...) Expand all Loading... |
| 283 if (unhandled->isFocusable()) | 273 if (unhandled->isFocusable()) |
| 284 continue; | 274 continue; |
| 285 String message("An invalid form control with name='%name' is not foc
usable."); | 275 String message("An invalid form control with name='%name' is not foc
usable."); |
| 286 message.replace("%name", unhandled->name()); | 276 message.replace("%name", unhandled->name()); |
| 287 document().addConsoleMessage(ConsoleMessage::create(RenderingMessage
Source, ErrorMessageLevel, message)); | 277 document().addConsoleMessage(ConsoleMessage::create(RenderingMessage
Source, ErrorMessageLevel, message)); |
| 288 } | 278 } |
| 289 } | 279 } |
| 290 return false; | 280 return false; |
| 291 } | 281 } |
| 292 | 282 |
| 293 void HTMLFormElement::prepareForSubmission(Event* event) | 283 void HTMLFormElement::prepareForSubmission(Event* event, HTMLFormControlElement*
submitButton) |
| 294 { | 284 { |
| 295 LocalFrame* frame = document().frame(); | 285 LocalFrame* frame = document().frame(); |
| 296 if (!frame || m_isSubmitting || m_inUserJSSubmitEvent) | 286 if (!frame || m_isSubmitting || m_inUserJSSubmitEvent) |
| 297 return; | 287 return; |
| 298 | 288 |
| 299 if (document().isSandboxed(SandboxForms)) { | 289 if (document().isSandboxed(SandboxForms)) { |
| 300 document().addConsoleMessage(ConsoleMessage::create(SecurityMessageSourc
e, ErrorMessageLevel, "Blocked form submission to '" + m_attributes.action() + "
' because the form's frame is sandboxed and the 'allow-forms' permission is not
set.")); | 290 document().addConsoleMessage(ConsoleMessage::create(SecurityMessageSourc
e, ErrorMessageLevel, "Blocked form submission to '" + m_attributes.action() + "
' because the form's frame is sandboxed and the 'allow-forms' permission is not
set.")); |
| 301 return; | 291 return; |
| 302 } | 292 } |
| 303 | 293 |
| 304 bool skipValidation = !document().page() || noValidate(); | 294 bool skipValidation = !document().page() || noValidate(); |
| 305 DCHECK(event); | 295 DCHECK(event); |
| 306 HTMLFormControlElement* submitElement = submitElementFromEvent(event); | 296 if (submitButton && submitButton->formNoValidate()) |
| 307 if (submitElement && submitElement->formNoValidate()) | |
| 308 skipValidation = true; | 297 skipValidation = true; |
| 309 | 298 |
| 310 UseCounter::count(document(), UseCounter::FormSubmissionStarted); | 299 UseCounter::count(document(), UseCounter::FormSubmissionStarted); |
| 311 // Interactive validation must be done before dispatching the submit event. | 300 // Interactive validation must be done before dispatching the submit event. |
| 312 if (!skipValidation && !validateInteractively()) | 301 if (!skipValidation && !validateInteractively()) |
| 313 return; | 302 return; |
| 314 | 303 |
| 315 bool shouldSubmit; | 304 bool shouldSubmit; |
| 316 { | 305 { |
| 317 AutoReset<bool> submitEventHandlerScope(&m_inUserJSSubmitEvent, true); | 306 AutoReset<bool> submitEventHandlerScope(&m_inUserJSSubmitEvent, true); |
| 318 frame->loader().client()->dispatchWillSendSubmitEvent(this); | 307 frame->loader().client()->dispatchWillSendSubmitEvent(this); |
| 319 shouldSubmit = dispatchEvent(Event::createCancelableBubble(EventTypeName
s::submit)) == DispatchEventResult::NotCanceled; | 308 shouldSubmit = dispatchEvent(Event::createCancelableBubble(EventTypeName
s::submit)) == DispatchEventResult::NotCanceled; |
| 320 } | 309 } |
| 321 if (shouldSubmit) { | 310 if (shouldSubmit) { |
| 322 m_plannedNavigation = nullptr; | 311 m_plannedNavigation = nullptr; |
| 323 submit(event, true); | 312 submit(event, submitButton); |
| 324 } | 313 } |
| 325 if (!m_plannedNavigation) | 314 if (!m_plannedNavigation) |
| 326 return; | 315 return; |
| 327 AutoReset<bool> submitScope(&m_isSubmitting, true); | 316 AutoReset<bool> submitScope(&m_isSubmitting, true); |
| 328 scheduleFormSubmission(m_plannedNavigation); | 317 scheduleFormSubmission(m_plannedNavigation); |
| 329 m_plannedNavigation = nullptr; | 318 m_plannedNavigation = nullptr; |
| 330 } | 319 } |
| 331 | 320 |
| 332 void HTMLFormElement::submitFromJavaScript() | 321 void HTMLFormElement::submitFromJavaScript() |
| 333 { | 322 { |
| 334 submit(0, false); | 323 submit(nullptr, nullptr); |
| 335 } | 324 } |
| 336 | 325 |
| 337 void HTMLFormElement::submitDialog(FormSubmission* formSubmission) | 326 void HTMLFormElement::submitDialog(FormSubmission* formSubmission) |
| 338 { | 327 { |
| 339 for (Node* node = this; node; node = node->parentOrShadowHostNode()) { | 328 for (Node* node = this; node; node = node->parentOrShadowHostNode()) { |
| 340 if (isHTMLDialogElement(*node)) { | 329 if (isHTMLDialogElement(*node)) { |
| 341 toHTMLDialogElement(*node).closeDialog(formSubmission->result()); | 330 toHTMLDialogElement(*node).closeDialog(formSubmission->result()); |
| 342 return; | 331 return; |
| 343 } | 332 } |
| 344 } | 333 } |
| 345 } | 334 } |
| 346 | 335 |
| 347 void HTMLFormElement::submit(Event* event, bool activateSubmitButton) | 336 void HTMLFormElement::submit(Event* event, HTMLFormControlElement* submitButton) |
| 348 { | 337 { |
| 349 FrameView* view = document().view(); | 338 FrameView* view = document().view(); |
| 350 LocalFrame* frame = document().frame(); | 339 LocalFrame* frame = document().frame(); |
| 351 if (!view || !frame || !frame->page()) | 340 if (!view || !frame || !frame->page()) |
| 352 return; | 341 return; |
| 353 | 342 |
| 354 // https://html.spec.whatwg.org/multipage/forms.html#form-submission-algorit
hm | 343 // https://html.spec.whatwg.org/multipage/forms.html#form-submission-algorit
hm |
| 355 // 2. If form document is not connected, has no associated browsing context, | 344 // 2. If form document is not connected, has no associated browsing context, |
| 356 // or its active sandboxing flag set has its sandboxed forms browsing | 345 // or its active sandboxing flag set has its sandboxed forms browsing |
| 357 // context flag set, then abort these steps without doing anything. | 346 // context flag set, then abort these steps without doing anything. |
| 358 if (!isConnected()) | 347 if (!isConnected()) |
| 359 return; | 348 return; |
| 360 | 349 |
| 361 if (m_isSubmitting) | 350 if (m_isSubmitting) |
| 362 return; | 351 return; |
| 363 | 352 |
| 364 // Delay dispatching 'close' to dialog until done submitting. | 353 // Delay dispatching 'close' to dialog until done submitting. |
| 365 EventQueueScope scopeForDialogClose; | 354 EventQueueScope scopeForDialogClose; |
| 366 AutoReset<bool> submitScope(&m_isSubmitting, true); | 355 AutoReset<bool> submitScope(&m_isSubmitting, true); |
| 367 | 356 |
| 368 HTMLFormControlElement* firstSuccessfulSubmitButton = nullptr; | 357 if (event && !submitButton) { |
| 369 bool needButtonActivation = activateSubmitButton; // do we need to activate
a submit button? | 358 // In a case of implicit submission without a submit button, 'submit' |
| 370 | 359 // event handler might add a submit button. We search for a submit |
| 371 const FormAssociatedElement::List& elements = associatedElements(); | 360 // button again. |
| 372 for (unsigned i = 0; i < elements.size(); ++i) { | 361 // TODO(tkent): Do we really need to activate such submit button? |
| 373 FormAssociatedElement* associatedElement = elements[i]; | 362 for (const auto& associatedElement : associatedElements()) { |
| 374 if (!associatedElement->isFormControlElement()) | 363 if (!associatedElement->isFormControlElement()) |
| 375 continue; | 364 continue; |
| 376 if (needButtonActivation) { | |
| 377 HTMLFormControlElement* control = toHTMLFormControlElement(associate
dElement); | 365 HTMLFormControlElement* control = toHTMLFormControlElement(associate
dElement); |
| 378 if (control->isActivatedSubmit()) | 366 DCHECK(!control->isActivatedSubmit()); |
| 379 needButtonActivation = false; | 367 if (control->isSuccessfulSubmitButton()) { |
| 380 else if (firstSuccessfulSubmitButton == 0 && control->isSuccessfulSu
bmitButton()) | 368 submitButton = control; |
| 381 firstSuccessfulSubmitButton = control; | 369 break; |
| 370 } |
| 382 } | 371 } |
| 383 } | 372 } |
| 384 | 373 |
| 385 if (needButtonActivation && firstSuccessfulSubmitButton) | 374 FormSubmission* formSubmission = FormSubmission::create(this, m_attributes,
event, submitButton); |
| 386 firstSuccessfulSubmitButton->setActivatedSubmit(true); | |
| 387 | |
| 388 FormSubmission* formSubmission = FormSubmission::create(this, m_attributes,
event); | |
| 389 if (formSubmission->method() == FormSubmission::DialogMethod) { | 375 if (formSubmission->method() == FormSubmission::DialogMethod) { |
| 390 submitDialog(formSubmission); | 376 submitDialog(formSubmission); |
| 391 } else if (m_inUserJSSubmitEvent) { | 377 } else if (m_inUserJSSubmitEvent) { |
| 392 // Need to postpone the submission in order to make this cancelable by | 378 // Need to postpone the submission in order to make this cancelable by |
| 393 // another submission request. | 379 // another submission request. |
| 394 m_plannedNavigation = formSubmission; | 380 m_plannedNavigation = formSubmission; |
| 395 } else { | 381 } else { |
| 396 // This runs JavaScript code if action attribute value is javascript: | 382 // This runs JavaScript code if action attribute value is javascript: |
| 397 // protocol. | 383 // protocol. |
| 398 scheduleFormSubmission(formSubmission); | 384 scheduleFormSubmission(formSubmission); |
| 399 } | 385 } |
| 400 | |
| 401 if (needButtonActivation && firstSuccessfulSubmitButton) | |
| 402 firstSuccessfulSubmitButton->setActivatedSubmit(false); | |
| 403 } | 386 } |
| 404 | 387 |
| 405 void HTMLFormElement::scheduleFormSubmission(FormSubmission* submission) | 388 void HTMLFormElement::scheduleFormSubmission(FormSubmission* submission) |
| 406 { | 389 { |
| 407 DCHECK(submission->method() == FormSubmission::PostMethod || submission->met
hod() == FormSubmission::GetMethod); | 390 DCHECK(submission->method() == FormSubmission::PostMethod || submission->met
hod() == FormSubmission::GetMethod); |
| 408 DCHECK(submission->data()); | 391 DCHECK(submission->data()); |
| 409 DCHECK(submission->form()); | 392 DCHECK(submission->form()); |
| 410 if (submission->action().isEmpty()) | 393 if (submission->action().isEmpty()) |
| 411 return; | 394 return; |
| 412 if (document().isSandboxed(SandboxForms)) { | 395 if (document().isSandboxed(SandboxForms)) { |
| (...skipping 386 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 799 { | 782 { |
| 800 for (const auto& control : associatedElements()) { | 783 for (const auto& control : associatedElements()) { |
| 801 if (!control->isFormControlElement()) | 784 if (!control->isFormControlElement()) |
| 802 continue; | 785 continue; |
| 803 if (toHTMLFormControlElement(control)->canBeSuccessfulSubmitButton()) | 786 if (toHTMLFormControlElement(control)->canBeSuccessfulSubmitButton()) |
| 804 toHTMLFormControlElement(control)->pseudoStateChanged(CSSSelector::P
seudoDefault); | 787 toHTMLFormControlElement(control)->pseudoStateChanged(CSSSelector::P
seudoDefault); |
| 805 } | 788 } |
| 806 } | 789 } |
| 807 | 790 |
| 808 } // namespace blink | 791 } // namespace blink |
| OLD | NEW |