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 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
48 #include "core/html/RadioNodeList.h" | 48 #include "core/html/RadioNodeList.h" |
49 #include "core/html/forms/FormController.h" | 49 #include "core/html/forms/FormController.h" |
50 #include "core/inspector/ConsoleMessage.h" | 50 #include "core/inspector/ConsoleMessage.h" |
51 #include "core/loader/FormSubmission.h" | 51 #include "core/loader/FormSubmission.h" |
52 #include "core/loader/FrameLoader.h" | 52 #include "core/loader/FrameLoader.h" |
53 #include "core/loader/FrameLoaderClient.h" | 53 #include "core/loader/FrameLoaderClient.h" |
54 #include "core/loader/MixedContentChecker.h" | 54 #include "core/loader/MixedContentChecker.h" |
55 #include "core/loader/NavigationScheduler.h" | 55 #include "core/loader/NavigationScheduler.h" |
56 #include "platform/UserGestureIndicator.h" | 56 #include "platform/UserGestureIndicator.h" |
57 #include "public/platform/WebInsecureRequestPolicy.h" | 57 #include "public/platform/WebInsecureRequestPolicy.h" |
| 58 #include "wtf/AutoReset.h" |
58 #include "wtf/text/AtomicString.h" | 59 #include "wtf/text/AtomicString.h" |
59 #include <limits> | 60 #include <limits> |
60 | 61 |
61 namespace blink { | 62 namespace blink { |
62 | 63 |
63 using namespace HTMLNames; | 64 using namespace HTMLNames; |
64 | 65 |
65 HTMLFormElement::HTMLFormElement(Document& document) | 66 HTMLFormElement::HTMLFormElement(Document& document) |
66 : HTMLElement(formTag, document) | 67 : HTMLElement(formTag, document) |
67 , m_associatedElementsAreDirty(false) | 68 , m_associatedElementsAreDirty(false) |
68 , m_imageElementsAreDirty(false) | 69 , m_imageElementsAreDirty(false) |
69 , m_hasElementsAssociatedByParser(false) | 70 , m_hasElementsAssociatedByParser(false) |
70 , m_hasElementsAssociatedByFormAttribute(false) | 71 , m_hasElementsAssociatedByFormAttribute(false) |
71 , m_didFinishParsingChildren(false) | 72 , m_didFinishParsingChildren(false) |
72 , m_isSubmittingOrInUserJSSubmitEvent(false) | |
73 , m_shouldSubmit(false) | 73 , m_shouldSubmit(false) |
74 , m_isInResetFunction(false) | 74 , m_isInResetFunction(false) |
75 , m_wasDemoted(false) | 75 , m_wasDemoted(false) |
76 { | 76 { |
77 } | 77 } |
78 | 78 |
79 HTMLFormElement* HTMLFormElement::create(Document& document) | 79 HTMLFormElement* HTMLFormElement::create(Document& document) |
80 { | 80 { |
81 UseCounter::count(document, UseCounter::FormElement); | 81 UseCounter::count(document, UseCounter::FormElement); |
82 return new HTMLFormElement(document); | 82 return new HTMLFormElement(document); |
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
286 message.replace("%name", unhandled->name()); | 286 message.replace("%name", unhandled->name()); |
287 document().addConsoleMessage(ConsoleMessage::create(RenderingMessage
Source, ErrorMessageLevel, message)); | 287 document().addConsoleMessage(ConsoleMessage::create(RenderingMessage
Source, ErrorMessageLevel, message)); |
288 } | 288 } |
289 } | 289 } |
290 return false; | 290 return false; |
291 } | 291 } |
292 | 292 |
293 void HTMLFormElement::prepareForSubmission(Event* event) | 293 void HTMLFormElement::prepareForSubmission(Event* event) |
294 { | 294 { |
295 LocalFrame* frame = document().frame(); | 295 LocalFrame* frame = document().frame(); |
296 if (!frame || m_isSubmittingOrInUserJSSubmitEvent) | 296 if (!frame || m_isSubmitting || m_inUserJSSubmitEvent) |
297 return; | 297 return; |
298 | 298 |
299 if (document().isSandboxed(SandboxForms)) { | 299 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.")); | 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.")); |
301 return; | 301 return; |
302 } | 302 } |
303 | 303 |
304 bool skipValidation = !document().page() || noValidate(); | 304 bool skipValidation = !document().page() || noValidate(); |
305 ASSERT(event); | 305 ASSERT(event); |
306 HTMLFormControlElement* submitElement = submitElementFromEvent(event); | 306 HTMLFormControlElement* submitElement = submitElementFromEvent(event); |
307 if (submitElement && submitElement->formNoValidate()) | 307 if (submitElement && submitElement->formNoValidate()) |
308 skipValidation = true; | 308 skipValidation = true; |
309 | 309 |
310 UseCounter::count(document(), UseCounter::FormSubmissionStarted); | 310 UseCounter::count(document(), UseCounter::FormSubmissionStarted); |
311 // Interactive validation must be done before dispatching the submit event. | 311 // Interactive validation must be done before dispatching the submit event. |
312 if (!skipValidation && !validateInteractively()) | 312 if (!skipValidation && !validateInteractively()) |
313 return; | 313 return; |
314 | 314 |
315 m_isSubmittingOrInUserJSSubmitEvent = true; | 315 { |
316 m_shouldSubmit = false; | 316 AutoReset<bool> submitEventHandlerScope(&m_inUserJSSubmitEvent, true); |
317 | 317 m_shouldSubmit = false; |
318 frame->loader().client()->dispatchWillSendSubmitEvent(this); | 318 frame->loader().client()->dispatchWillSendSubmitEvent(this); |
319 | 319 if (dispatchEvent(Event::createCancelableBubble(EventTypeNames::submit))
== DispatchEventResult::NotCanceled) |
320 if (dispatchEvent(Event::createCancelableBubble(EventTypeNames::submit)) ==
DispatchEventResult::NotCanceled) | 320 m_shouldSubmit = true; |
321 m_shouldSubmit = true; | 321 } |
322 | |
323 m_isSubmittingOrInUserJSSubmitEvent = false; | |
324 | 322 |
325 if (m_shouldSubmit) | 323 if (m_shouldSubmit) |
326 submit(event, true); | 324 submit(event, true); |
327 } | 325 } |
328 | 326 |
329 void HTMLFormElement::submitFromJavaScript() | 327 void HTMLFormElement::submitFromJavaScript() |
330 { | 328 { |
331 submit(0, false); | 329 submit(0, false); |
332 } | 330 } |
333 | 331 |
(...skipping 10 matching lines...) Expand all Loading... |
344 void HTMLFormElement::submit(Event* event, bool activateSubmitButton) | 342 void HTMLFormElement::submit(Event* event, bool activateSubmitButton) |
345 { | 343 { |
346 FrameView* view = document().view(); | 344 FrameView* view = document().view(); |
347 LocalFrame* frame = document().frame(); | 345 LocalFrame* frame = document().frame(); |
348 if (!view || !frame || !frame->page()) | 346 if (!view || !frame || !frame->page()) |
349 return; | 347 return; |
350 // See crbug.com/586749. | 348 // See crbug.com/586749. |
351 if (!isConnected()) | 349 if (!isConnected()) |
352 UseCounter::count(document(), UseCounter::FormSubmissionNotInDocumentTre
e); | 350 UseCounter::count(document(), UseCounter::FormSubmissionNotInDocumentTre
e); |
353 | 351 |
354 if (m_isSubmittingOrInUserJSSubmitEvent) { | 352 if (m_isSubmitting || m_inUserJSSubmitEvent) { |
355 m_shouldSubmit = true; | 353 m_shouldSubmit = true; |
356 return; | 354 return; |
357 } | 355 } |
358 | 356 |
359 m_isSubmittingOrInUserJSSubmitEvent = true; | 357 // Delay dispatching 'close' to dialog until done submitting. |
| 358 EventQueueScope scopeForDialogClose; |
| 359 AutoReset<bool> submitScope(&m_isSubmitting, true); |
360 | 360 |
361 HTMLFormControlElement* firstSuccessfulSubmitButton = nullptr; | 361 HTMLFormControlElement* firstSuccessfulSubmitButton = nullptr; |
362 bool needButtonActivation = activateSubmitButton; // do we need to activate
a submit button? | 362 bool needButtonActivation = activateSubmitButton; // do we need to activate
a submit button? |
363 | 363 |
364 const FormAssociatedElement::List& elements = associatedElements(); | 364 const FormAssociatedElement::List& elements = associatedElements(); |
365 for (unsigned i = 0; i < elements.size(); ++i) { | 365 for (unsigned i = 0; i < elements.size(); ++i) { |
366 FormAssociatedElement* associatedElement = elements[i]; | 366 FormAssociatedElement* associatedElement = elements[i]; |
367 if (!associatedElement->isFormControlElement()) | 367 if (!associatedElement->isFormControlElement()) |
368 continue; | 368 continue; |
369 if (needButtonActivation) { | 369 if (needButtonActivation) { |
370 HTMLFormControlElement* control = toHTMLFormControlElement(associate
dElement); | 370 HTMLFormControlElement* control = toHTMLFormControlElement(associate
dElement); |
371 if (control->isActivatedSubmit()) | 371 if (control->isActivatedSubmit()) |
372 needButtonActivation = false; | 372 needButtonActivation = false; |
373 else if (firstSuccessfulSubmitButton == 0 && control->isSuccessfulSu
bmitButton()) | 373 else if (firstSuccessfulSubmitButton == 0 && control->isSuccessfulSu
bmitButton()) |
374 firstSuccessfulSubmitButton = control; | 374 firstSuccessfulSubmitButton = control; |
375 } | 375 } |
376 } | 376 } |
377 | 377 |
378 if (needButtonActivation && firstSuccessfulSubmitButton) | 378 if (needButtonActivation && firstSuccessfulSubmitButton) |
379 firstSuccessfulSubmitButton->setActivatedSubmit(true); | 379 firstSuccessfulSubmitButton->setActivatedSubmit(true); |
380 | 380 |
381 FormSubmission* formSubmission = FormSubmission::create(this, m_attributes,
event); | 381 FormSubmission* formSubmission = FormSubmission::create(this, m_attributes,
event); |
382 EventQueueScope scopeForDialogClose; // Delay dispatching 'close' to dialog
until done submitting. | 382 if (formSubmission->method() == FormSubmission::DialogMethod) { |
383 if (formSubmission->method() == FormSubmission::DialogMethod) | |
384 submitDialog(formSubmission); | 383 submitDialog(formSubmission); |
385 else | 384 } else { |
| 385 // This runs JavaScript code if action attribute value is javascript: |
| 386 // protocol. |
386 scheduleFormSubmission(formSubmission); | 387 scheduleFormSubmission(formSubmission); |
| 388 } |
387 | 389 |
388 if (needButtonActivation && firstSuccessfulSubmitButton) | 390 if (needButtonActivation && firstSuccessfulSubmitButton) |
389 firstSuccessfulSubmitButton->setActivatedSubmit(false); | 391 firstSuccessfulSubmitButton->setActivatedSubmit(false); |
390 | 392 |
391 m_shouldSubmit = false; | 393 m_shouldSubmit = false; |
392 m_isSubmittingOrInUserJSSubmitEvent = false; | |
393 } | 394 } |
394 | 395 |
395 void HTMLFormElement::scheduleFormSubmission(FormSubmission* submission) | 396 void HTMLFormElement::scheduleFormSubmission(FormSubmission* submission) |
396 { | 397 { |
397 ASSERT(submission->method() == FormSubmission::PostMethod || submission->met
hod() == FormSubmission::GetMethod); | 398 ASSERT(submission->method() == FormSubmission::PostMethod || submission->met
hod() == FormSubmission::GetMethod); |
398 ASSERT(submission->data()); | 399 ASSERT(submission->data()); |
399 ASSERT(submission->form()); | 400 ASSERT(submission->form()); |
400 if (submission->action().isEmpty()) | 401 if (submission->action().isEmpty()) |
401 return; | 402 return; |
402 if (document().isSandboxed(SandboxForms)) { | 403 if (document().isSandboxed(SandboxForms)) { |
(...skipping 386 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
789 { | 790 { |
790 for (const auto& control : associatedElements()) { | 791 for (const auto& control : associatedElements()) { |
791 if (!control->isFormControlElement()) | 792 if (!control->isFormControlElement()) |
792 continue; | 793 continue; |
793 if (toHTMLFormControlElement(control)->canBeSuccessfulSubmitButton()) | 794 if (toHTMLFormControlElement(control)->canBeSuccessfulSubmitButton()) |
794 toHTMLFormControlElement(control)->pseudoStateChanged(CSSSelector::P
seudoDefault); | 795 toHTMLFormControlElement(control)->pseudoStateChanged(CSSSelector::P
seudoDefault); |
795 } | 796 } |
796 } | 797 } |
797 | 798 |
798 } // namespace blink | 799 } // namespace blink |
OLD | NEW |