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 |