Skip to content

Commit

Permalink
Bug 1551758 - Centralize form submission; r=smaug
Browse files Browse the repository at this point in the history
Differential Revision: https://phabricator.services.mozilla.com/D53165

--HG--
extra : moz-landing-system : lando
johndai1984 committed Nov 20, 2019
1 parent 1ff253a commit a9103e9
Showing 5 changed files with 82 additions and 95 deletions.
30 changes: 8 additions & 22 deletions dom/html/HTMLButtonElement.cpp
Original file line number Diff line number Diff line change
@@ -250,29 +250,15 @@ nsresult HTMLButtonElement::PostHandleEvent(EventChainPostVisitor& aVisitor) {
break;
}
if (aVisitor.mItemFlags & NS_OUTER_ACTIVATE_EVENT) {
if (mForm &&
(mType == NS_FORM_BUTTON_SUBMIT || mType == NS_FORM_BUTTON_RESET)) {
InternalFormEvent event(
true, (mType == NS_FORM_BUTTON_RESET) ? eFormReset : eFormSubmit);
event.mOriginator = this;
nsEventStatus status = nsEventStatus_eIgnore;

RefPtr<PresShell> presShell = aVisitor.mPresContext->GetPresShell();
// If |PresShell::Destroy| has been called due to
// handling the event, the pres context will return
// a null pres shell. See bug 125624.
//
// Using presShell to dispatch the event. It makes sure that
// event is not handled if the window is being destroyed.
if (presShell && (event.mMessage != eFormSubmit ||
mForm->SubmissionCanProceed(this))) {
// TODO: removing this code and have the submit event sent by the form
// see bug 592124.
// Hold a strong ref while dispatching
RefPtr<HTMLFormElement> form(mForm);
presShell->HandleDOMEventWithTarget(form, &event, &status);
aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
if (mForm) {
// Hold a strong ref while dispatching
RefPtr<mozilla::dom::HTMLFormElement> form(mForm);
if (mType == NS_FORM_BUTTON_RESET) {
form->MaybeReset(this);
} else if (mType == NS_FORM_BUTTON_SUBMIT) {
form->MaybeSubmit(this);
}
aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
}
}
} else if ((aVisitor.mItemFlags & NS_IN_SUBMIT_CLICK) && mForm) {
87 changes: 55 additions & 32 deletions dom/html/HTMLFormElement.cpp
Original file line number Diff line number Diff line change
@@ -218,6 +218,61 @@ void HTMLFormElement::GetMethod(nsAString& aValue) {
GetEnumAttr(nsGkAtoms::method, kFormDefaultMethod->tag, aValue);
}

// https://html.spec.whatwg.org/multipage/forms.html#concept-form-submit
void HTMLFormElement::MaybeSubmit(Element* aSubmitter) {
#ifdef DEBUG
if (aSubmitter) {
nsCOMPtr<nsIFormControl> fc = do_QueryInterface(aSubmitter);
MOZ_ASSERT(fc);
MOZ_ASSERT(fc->IsSubmitControl(), "aSubmitter is not a submit control?");
}
#endif

// 1-4 of
// https://html.spec.whatwg.org/multipage/forms.html#concept-form-submit
Document* doc = GetComposedDoc();
if (mIsConstructingEntryList || !doc ||
(doc->GetSandboxFlags() & SANDBOXED_FORMS)) {
return;
}

// 6.3. If the submitter element's no-validate state is false, then
// interactively validate the constraints of form and examine the result.
// If the result is negative (i.e., the constraint validation concluded
// that there were invalid fields and probably informed the user of this)
bool noValidateState =
HasAttr(kNameSpaceID_None, nsGkAtoms::novalidate) ||
(aSubmitter &&
aSubmitter->HasAttr(kNameSpaceID_None, nsGkAtoms::formnovalidate));
if (!noValidateState && !CheckValidFormSubmission()) {
return;
}

// If |PresShell::Destroy| has been called due to handling the event the pres
// context will return a null pres shell. See bug 125624. Using presShell to
// dispatch the event. It makes sure that event is not handled if the window
// is being destroyed.
if (RefPtr<PresShell> presShell = doc->GetPresShell()) {
InternalFormEvent event(true, eFormSubmit);
event.mOriginator = aSubmitter;
nsEventStatus status = nsEventStatus_eIgnore;
presShell->HandleDOMEventWithTarget(this, &event, &status);
}
}

void HTMLFormElement::MaybeReset(Element* aSubmitter) {
// If |PresShell::Destroy| has been called due to handling the event the pres
// context will return a null pres shell. See bug 125624. Using presShell to
// dispatch the event. It makes sure that event is not handled if the window
// is being destroyed.
if (RefPtr<PresShell> presShell = OwnerDoc()->GetPresShell()) {
InternalFormEvent event(true, eFormReset);
event.mOriginator = aSubmitter;
nsEventStatus status = nsEventStatus_eIgnore;
presShell->HandleDOMEventWithTarget(this, &event, &status);
}
}

void HTMLFormElement::Submit(ErrorResult& aRv) {
// Send the submit event
if (mPendingSubmission) {
@@ -1863,38 +1918,6 @@ One should be implemented!");
return result;
}

bool HTMLFormElement::SubmissionCanProceed(Element* aSubmitter) {
#ifdef DEBUG
if (aSubmitter) {
nsCOMPtr<nsIFormControl> fc = do_QueryInterface(aSubmitter);
MOZ_ASSERT(fc);

uint32_t type = fc->ControlType();
MOZ_ASSERT(type == NS_FORM_INPUT_SUBMIT || type == NS_FORM_INPUT_IMAGE ||
type == NS_FORM_BUTTON_SUBMIT,
"aSubmitter is not a submit control?");
}
#endif

// Modified step 2 of
// https://html.spec.whatwg.org/multipage/forms.html#concept-form-submit --
// we're not checking whether the node document is disconnected yet...
if (OwnerDoc()->GetSandboxFlags() & SANDBOXED_FORMS) {
return false;
}

if (HasAttr(kNameSpaceID_None, nsGkAtoms::novalidate)) {
return true;
}

if (aSubmitter &&
aSubmitter->HasAttr(kNameSpaceID_None, nsGkAtoms::formnovalidate)) {
return true;
}

return CheckValidFormSubmission();
}

void HTMLFormElement::UpdateValidity(bool aElementValidity) {
if (aElementValidity) {
--mInvalidElementsCount;
18 changes: 9 additions & 9 deletions dom/html/HTMLFormElement.h
Original file line number Diff line number Diff line change
@@ -267,15 +267,6 @@ class HTMLFormElement final : public nsGenericHTMLElement,
*/
bool CheckValidFormSubmission();

/**
* Check whether submission can proceed for this form. This basically
* implements steps 1-4 (more or less) of
* <https://html.spec.whatwg.org/multipage/forms.html#concept-form-submit>.
* aSubmitter, if not null, is the "submitter" from that algorithm. Therefore
* it must be a valid submit control.
*/
bool SubmissionCanProceed(Element* aSubmitter);

/**
* Contruct the entry list to get their data pumped into the FormData and
* fire a `formdata` event with the entry list in formData attribute.
@@ -360,6 +351,15 @@ class HTMLFormElement final : public nsGenericHTMLElement,

int32_t Length();

/**
* Check whether submission can proceed for this form then fire submit event.
* This basically implements steps 1-6 (more or less) of
* <https://html.spec.whatwg.org/multipage/forms.html#concept-form-submit>.
* @param aSubmitter If not null, is the "submitter" from that algorithm.
* Therefore it must be a valid submit control.
*/
MOZ_CAN_RUN_SCRIPT void MaybeSubmit(Element* aSubmitter);
MOZ_CAN_RUN_SCRIPT void MaybeReset(Element* aSubmitter);
void Submit(ErrorResult& aRv);
void Reset();

38 changes: 10 additions & 28 deletions dom/html/HTMLInputElement.cpp
Original file line number Diff line number Diff line change
@@ -2906,16 +2906,11 @@ nsresult HTMLInputElement::MaybeSubmitForm(nsPresContext* aPresContext) {
WidgetMouseEvent event(true, eMouseClick, nullptr, WidgetMouseEvent::eReal);
nsEventStatus status = nsEventStatus_eIgnore;
presShell->HandleDOMEventWithTarget(submitContent, &event, &status);
} else if (!mForm->ImplicitSubmissionIsDisabled() &&
mForm->SubmissionCanProceed(nullptr)) {
// TODO: removing this code and have the submit event sent by the form,
// bug 592124.
} else if (!mForm->ImplicitSubmissionIsDisabled()) {
// If there's only one text control, just submit the form
// Hold strong ref across the event
RefPtr<mozilla::dom::HTMLFormElement> form = mForm;
InternalFormEvent event(true, eFormSubmit);
nsEventStatus status = nsEventStatus_eIgnore;
presShell->HandleDOMEventWithTarget(form, &event, &status);
RefPtr<mozilla::dom::HTMLFormElement> form(mForm);
form->MaybeSubmit(nullptr);
}

return NS_OK;
@@ -4155,27 +4150,14 @@ nsresult HTMLInputElement::PostHandleEvent(EventChainPostVisitor& aVisitor) {
case NS_FORM_INPUT_SUBMIT:
case NS_FORM_INPUT_IMAGE:
if (mForm) {
InternalFormEvent event(true, (mType == NS_FORM_INPUT_RESET)
? eFormReset
: eFormSubmit);
event.mOriginator = this;
nsEventStatus status = nsEventStatus_eIgnore;

RefPtr<PresShell> presShell =
aVisitor.mPresContext->GetPresShell();

// If |PresShell::Destroy| has been called due to
// handling the event the pres context will return a null
// pres shell. See bug 125624.
// TODO: removing this code and have the submit event sent by the
// form, see bug 592124.
if (presShell && (event.mMessage != eFormSubmit ||
mForm->SubmissionCanProceed(this))) {
// Hold a strong ref while dispatching
RefPtr<mozilla::dom::HTMLFormElement> form(mForm);
presShell->HandleDOMEventWithTarget(form, &event, &status);
aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
// Hold a strong ref while dispatching
RefPtr<mozilla::dom::HTMLFormElement> form(mForm);
if (mType == NS_FORM_INPUT_RESET) {
form->MaybeReset(this);
} else {
form->MaybeSubmit(this);
}
aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
}
break;

This file was deleted.

0 comments on commit a9103e9

Please sign in to comment.