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