Commit 864df709 authored by tkent's avatar tkent Committed by Commit bot

submit() in submit event handler should not contains a value of a submit button.

The value of a submit button is appended to a FormData if its activatedSubmit flag
is set.
In a case of form.submit() is called in submit event handler, we did:

1. Set activatedSubmit flag of the submit button
2. Dispatch submit event
2.1. form.submit() builds FormData
3. Build FormData if the submit event was not prevented
4. Clear activatedSubmit flag of the submit button

In step 2.1, we should not include the submit button. So, this CL changes the
process as follows:

1. Dispatch submit event
1.1 form.submit() builds FormData
2. If the submit event was not prevented,
2.1. Set activatedSubmit flag of the submit button
2.2. Build FormData
2.3. Clear activatedSubmit flag of the submit button

Implementation:
We called setActivatedSubmit() before/after prepareForSubmission(). Instead, we
pass a submit button element to prepareForSubmission(), and call
setActivatedSubmit() just before/after building FormData.

BUG=646790

Review-Url: https://codereview.chromium.org/2340213002
Cr-Commit-Position: refs/heads/master@{#419073}
parent ecf51ddf
<!DOCTYPE html>
<body>
<script src="../../resources/testharness.js"></script>
<script src="../../resources/testharnessreport.js"></script>
<iframe name="target"></iframe>
<form action="about:blank" onsubmit="this.submit(); return false;" target="target">
<input name="t" value="text">
<input type="submit" name="b" value="Next">
</form>
<script>
var test = async_test('submit() in submit event handler should not contains a value of a submit button.');
test.step(() => {
var iframe = document.querySelector('iframe');
iframe.addEventListener('load', test.step_func(() => {
assert_true(iframe.contentWindow.location.href.endsWith('?t=text'));
test.done();
}), false);
document.querySelector('input[type=submit]').click();
});
</script>
......@@ -114,10 +114,8 @@ void HTMLButtonElement::defaultEventHandler(Event* event)
{
if (event->type() == EventTypeNames::DOMActivate && !isDisabledFormControl()) {
if (form() && m_type == SUBMIT) {
m_isActivatedSubmit = true;
form()->prepareForSubmission(event);
form()->prepareForSubmission(event, this);
event->setDefaultHandled();
m_isActivatedSubmit = false; // Do this in case submission was canceled.
}
if (form() && m_type == RESET) {
form()->reset();
......
......@@ -235,17 +235,7 @@ void HTMLFormElement::submitImplicitly(Event* event, bool fromImplicitSubmission
}
}
if (fromImplicitSubmissionTrigger && submissionTriggerCount == 1)
prepareForSubmission(event);
}
// FIXME: Consolidate this and similar code in FormSubmission.cpp.
static inline HTMLFormControlElement* submitElementFromEvent(const Event* event)
{
for (Node* node = event->target()->toNode(); node; node = node->parentOrShadowHostNode()) {
if (node->isElementNode() && toElement(node)->isFormControlElement())
return toHTMLFormControlElement(node);
}
return 0;
prepareForSubmission(event, nullptr);
}
bool HTMLFormElement::validateInteractively()
......@@ -291,7 +281,7 @@ bool HTMLFormElement::validateInteractively()
return false;
}
void HTMLFormElement::prepareForSubmission(Event* event)
void HTMLFormElement::prepareForSubmission(Event* event, HTMLFormControlElement* submitButton)
{
LocalFrame* frame = document().frame();
if (!frame || m_isSubmitting || m_inUserJSSubmitEvent)
......@@ -304,8 +294,7 @@ void HTMLFormElement::prepareForSubmission(Event* event)
bool skipValidation = !document().page() || noValidate();
DCHECK(event);
HTMLFormControlElement* submitElement = submitElementFromEvent(event);
if (submitElement && submitElement->formNoValidate())
if (submitButton && submitButton->formNoValidate())
skipValidation = true;
UseCounter::count(document(), UseCounter::FormSubmissionStarted);
......@@ -321,7 +310,7 @@ void HTMLFormElement::prepareForSubmission(Event* event)
}
if (shouldSubmit) {
m_plannedNavigation = nullptr;
submit(event, true);
submit(event, submitButton);
}
if (!m_plannedNavigation)
return;
......@@ -332,7 +321,7 @@ void HTMLFormElement::prepareForSubmission(Event* event)
void HTMLFormElement::submitFromJavaScript()
{
submit(0, false);
submit(nullptr, nullptr);
}
void HTMLFormElement::submitDialog(FormSubmission* formSubmission)
......@@ -345,7 +334,7 @@ void HTMLFormElement::submitDialog(FormSubmission* formSubmission)
}
}
void HTMLFormElement::submit(Event* event, bool activateSubmitButton)
void HTMLFormElement::submit(Event* event, HTMLFormControlElement* submitButton)
{
FrameView* view = document().view();
LocalFrame* frame = document().frame();
......@@ -366,27 +355,24 @@ void HTMLFormElement::submit(Event* event, bool activateSubmitButton)
EventQueueScope scopeForDialogClose;
AutoReset<bool> submitScope(&m_isSubmitting, true);
HTMLFormControlElement* firstSuccessfulSubmitButton = nullptr;
bool needButtonActivation = activateSubmitButton; // do we need to activate a submit button?
const FormAssociatedElement::List& elements = associatedElements();
for (unsigned i = 0; i < elements.size(); ++i) {
FormAssociatedElement* associatedElement = elements[i];
if (!associatedElement->isFormControlElement())
continue;
if (needButtonActivation) {
if (event && !submitButton) {
// In a case of implicit submission without a submit button, 'submit'
// event handler might add a submit button. We search for a submit
// button again.
// TODO(tkent): Do we really need to activate such submit button?
for (const auto& associatedElement : associatedElements()) {
if (!associatedElement->isFormControlElement())
continue;
HTMLFormControlElement* control = toHTMLFormControlElement(associatedElement);
if (control->isActivatedSubmit())
needButtonActivation = false;
else if (firstSuccessfulSubmitButton == 0 && control->isSuccessfulSubmitButton())
firstSuccessfulSubmitButton = control;
DCHECK(!control->isActivatedSubmit());
if (control->isSuccessfulSubmitButton()) {
submitButton = control;
break;
}
}
}
if (needButtonActivation && firstSuccessfulSubmitButton)
firstSuccessfulSubmitButton->setActivatedSubmit(true);
FormSubmission* formSubmission = FormSubmission::create(this, m_attributes, event);
FormSubmission* formSubmission = FormSubmission::create(this, m_attributes, event, submitButton);
if (formSubmission->method() == FormSubmission::DialogMethod) {
submitDialog(formSubmission);
} else if (m_inUserJSSubmitEvent) {
......@@ -398,9 +384,6 @@ void HTMLFormElement::submit(Event* event, bool activateSubmitButton)
// protocol.
scheduleFormSubmission(formSubmission);
}
if (needButtonActivation && firstSuccessfulSubmitButton)
firstSuccessfulSubmitButton->setActivatedSubmit(false);
}
void HTMLFormElement::scheduleFormSubmission(FormSubmission* submission)
......
......@@ -66,7 +66,7 @@ public:
void disassociate(HTMLImageElement&);
void didAssociateByParser();
void prepareForSubmission(Event*);
void prepareForSubmission(Event*, HTMLFormControlElement* submitButton);
void submitFromJavaScript();
void reset();
......@@ -119,7 +119,7 @@ private:
void copyNonAttributePropertiesFromElement(const Element&) override;
void submitDialog(FormSubmission*);
void submit(Event*, bool activateSubmitButton);
void submit(Event*, HTMLFormControlElement* submitButton);
void scheduleFormSubmission(FormSubmission*);
......
......@@ -110,10 +110,8 @@ void ImageInputType::handleDOMActivateEvent(Event* event)
{
if (element().isDisabledFormControl() || !element().form())
return;
element().setActivatedSubmit(true);
m_clickLocation = extractClickLocation(event);
element().form()->prepareForSubmission(event); // Event handlers can run.
element().setActivatedSubmit(false);
element().form()->prepareForSubmission(event, &element()); // Event handlers can run.
event->setDefaultHandled();
}
......
......@@ -66,9 +66,7 @@ void SubmitInputType::handleDOMActivateEvent(Event* event)
{
if (element().isDisabledFormControl() || !element().form())
return;
element().setActivatedSubmit(true);
element().form()->prepareForSubmission(event); // Event handlers can run.
element().setActivatedSubmit(false);
element().form()->prepareForSubmission(event, &element()); // Event handlers can run.
event->setDefaultHandled();
}
......
......@@ -162,20 +162,10 @@ inline FormSubmission::FormSubmission(const String& result)
{
}
FormSubmission* FormSubmission::create(HTMLFormElement* form, const Attributes& attributes, Event* event)
FormSubmission* FormSubmission::create(HTMLFormElement* form, const Attributes& attributes, Event* event, HTMLFormControlElement* submitButton)
{
DCHECK(form);
HTMLFormControlElement* submitButton = 0;
if (event && event->target()) {
for (Node* node = event->target()->toNode(); node; node = node->parentOrShadowHostNode()) {
if (node->isElementNode() && toElement(node)->isFormControlElement()) {
submitButton = toHTMLFormControlElement(node);
break;
}
}
}
FormSubmission::Attributes copiedAttributes;
copiedAttributes.copyFrom(attributes);
if (submitButton) {
......@@ -220,6 +210,8 @@ FormSubmission* FormSubmission::create(HTMLFormElement* form, const Attributes&
WTF::TextEncoding dataEncoding = isMailtoForm ? UTF8Encoding() : FormDataEncoder::encodingFromAcceptCharset(copiedAttributes.acceptCharset(), document.encoding());
FormData* domFormData = FormData::create(dataEncoding.encodingForFormSubmission());
if (submitButton)
submitButton->setActivatedSubmit(true);
bool containsPasswordData = false;
for (unsigned i = 0; i < form->associatedElements().size(); ++i) {
FormAssociatedElement* control = form->associatedElements()[i];
......@@ -233,6 +225,8 @@ FormSubmission* FormSubmission::create(HTMLFormElement* form, const Attributes&
containsPasswordData = true;
}
}
if (submitButton)
submitButton->setActivatedSubmit(false);
RefPtr<EncodedFormData> formData;
String boundary;
......
......@@ -42,6 +42,7 @@ namespace blink {
class Document;
class EncodedFormData;
class Event;
class HTMLFormControlElement;
class HTMLFormElement;
class FormSubmission : public GarbageCollectedFinalized<FormSubmission> {
......@@ -90,7 +91,7 @@ public:
String m_acceptCharset;
};
static FormSubmission* create(HTMLFormElement*, const Attributes&, Event*);
static FormSubmission* create(HTMLFormElement*, const Attributes&, Event*, HTMLFormControlElement* submitButton);
DECLARE_TRACE();
FrameLoadRequest createFrameLoadRequest(Document* originDocument);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment