From 5683fcf7c8102f997dd92450999d0096ffd0253c Mon Sep 17 00:00:00 2001 From: John Dai Date: Tue, 11 Feb 2020 12:46:54 +0000 Subject: [PATCH] Bug 1588715 - Implement SubmitEvent; r=smaug Differential Revision: https://phabricator.services.mozilla.com/D62030 --HG-- extra : moz-landing-system : lando --- .../test/test_all_synthetic_events.html | 4 + dom/html/HTMLFormElement.cpp | 82 +++++++++---------- dom/html/HTMLFormElement.h | 7 +- .../mochitest/general/test_interfaces.js | 2 + dom/webidl/SubmitEvent.webidl | 19 +++++ dom/webidl/moz.build | 1 + .../meta/html/dom/idlharness.https.html.ini | 22 ----- .../SubmitEvent.window.js.ini | 19 ----- .../form-submission-algorithm.html.ini | 13 --- .../implicit-submission.optional.html.ini | 6 +- 10 files changed, 67 insertions(+), 108 deletions(-) create mode 100644 dom/webidl/SubmitEvent.webidl delete mode 100644 testing/web-platform/meta/html/semantics/forms/form-submission-0/SubmitEvent.window.js.ini delete mode 100644 testing/web-platform/meta/html/semantics/forms/form-submission-0/form-submission-algorithm.html.ini diff --git a/dom/events/test/test_all_synthetic_events.html b/dom/events/test/test_all_synthetic_events.html index 36044919a9f7..ac786043df93 100644 --- a/dom/events/test/test_all_synthetic_events.html +++ b/dom/events/test/test_all_synthetic_events.html @@ -344,6 +344,10 @@ const kEventConstructors = { }, chromeOnly: true, }, + SubmitEvent: { create (aName, aProps) { + return new SubmitEvent(aName, aProps); + }, + }, TCPSocketErrorEvent: { create(aName, aProps) { return new TCPSocketErrorEvent(aName, aProps); }, diff --git a/dom/html/HTMLFormElement.cpp b/dom/html/HTMLFormElement.cpp index c581d733c3fc..f5a6a6a52fa0 100644 --- a/dom/html/HTMLFormElement.cpp +++ b/dom/html/HTMLFormElement.cpp @@ -41,6 +41,7 @@ #include "HTMLFormSubmissionConstants.h" #include "mozilla/dom/FormData.h" #include "mozilla/dom/FormDataEvent.h" +#include "mozilla/dom/SubmitEvent.h" #include "mozilla/Telemetry.h" #include "nsIFormSubmitObserver.h" #include "nsIObserverService.h" @@ -260,10 +261,16 @@ void HTMLFormElement::MaybeSubmit(Element* aSubmitter) { // dispatch the event. It makes sure that event is not handled if the window // is being destroyed. if (RefPtr presShell = doc->GetPresShell()) { - InternalFormEvent event(true, eFormSubmit); - event.mOriginator = aSubmitter; + SubmitEventInit init; + init.mBubbles = true; + init.mCancelable = true; + init.mSubmitter = + aSubmitter ? nsGenericHTMLElement::FromNode(aSubmitter) : nullptr; + RefPtr event = + SubmitEvent::Constructor(this, NS_LITERAL_STRING("submit"), init); + event->SetTrusted(true); nsEventStatus status = nsEventStatus_eIgnore; - presShell->HandleDOMEventWithTarget(this, &event, &status); + presShell->HandleDOMEventWithTarget(this, event, &status); } } @@ -290,7 +297,7 @@ void HTMLFormElement::Submit(ErrorResult& aRv) { mPendingSubmission = nullptr; } - aRv = DoSubmitOrReset(nullptr, eFormSubmit); + aRv = DoSubmit(); } // https://html.spec.whatwg.org/multipage/forms.html#dom-form-requestsubmit @@ -541,9 +548,12 @@ nsresult HTMLFormElement::PostHandleEvent(EventChainPostVisitor& aVisitor) { if (aVisitor.mEventStatus == nsEventStatus_eIgnore) { switch (msg) { - case eFormReset: + case eFormReset: { + DoReset(); + break; + } case eFormSubmit: { - if (mPendingSubmission && msg == eFormSubmit) { + if (mPendingSubmission) { // tell the form to forget a possible pending submission. // the reason is that the script returned true (the event was // ignored) so if there is a stored submission, it will miss @@ -551,7 +561,7 @@ nsresult HTMLFormElement::PostHandleEvent(EventChainPostVisitor& aVisitor) { // to forget it and the form element will build a new one mPendingSubmission = nullptr; } - DoSubmitOrReset(aVisitor.mEvent, msg); + DoSubmit(aVisitor.mDOMEvent); break; } default: @@ -576,36 +586,13 @@ nsresult HTMLFormElement::PostHandleEvent(EventChainPostVisitor& aVisitor) { return NS_OK; } -nsresult HTMLFormElement::DoSubmitOrReset(WidgetEvent* aEvent, - EventMessage aMessage) { +nsresult HTMLFormElement::DoReset() { // Make sure the presentation is up-to-date Document* doc = GetComposedDoc(); if (doc) { doc->FlushPendingNotifications(FlushType::ContentAndNotify); } - // JBK Don't get form frames anymore - bug 34297 - - // Submit or Reset the form - if (eFormReset == aMessage) { - return DoReset(); - } - - if (eFormSubmit == aMessage) { - // Don't submit if we're not in a document or if we're in - // a sandboxed frame and form submit is disabled. - if (mIsConstructingEntryList || !doc || - (doc->GetSandboxFlags() & SANDBOXED_FORMS)) { - return NS_OK; - } - return DoSubmit(aEvent); - } - - MOZ_ASSERT(false); - return NS_OK; -} - -nsresult HTMLFormElement::DoReset() { mEverTriedInvalidSubmit = false; // JBK walk the elements[] array instead of form frame controls - bug 34297 uint32_t numElements = GetElementCount(); @@ -626,8 +613,21 @@ nsresult HTMLFormElement::DoReset() { return rv; \ } -nsresult HTMLFormElement::DoSubmit(WidgetEvent* aEvent) { - NS_ASSERTION(GetComposedDoc(), "Should never get here without a current doc"); +nsresult HTMLFormElement::DoSubmit(Event* aEvent) { + Document* doc = GetComposedDoc(); + NS_ASSERTION(doc, "Should never get here without a current doc"); + + // Make sure the presentation is up-to-date + if (doc) { + doc->FlushPendingNotifications(FlushType::ContentAndNotify); + } + + // Don't submit if we're not in a document or if we're in + // a sandboxed frame and form submit is disabled. + if (mIsConstructingEntryList || !doc || + (doc->GetSandboxFlags() & SANDBOXED_FORMS)) { + return NS_OK; + } if (mIsSubmitting) { NS_WARNING("Preventing double form submission"); @@ -685,21 +685,15 @@ nsresult HTMLFormElement::DoSubmit(WidgetEvent* aEvent) { } nsresult HTMLFormElement::BuildSubmission(HTMLFormSubmission** aFormSubmission, - WidgetEvent* aEvent) { + Event* aEvent) { NS_ASSERTION(!mPendingSubmission, "tried to build two submissions!"); - // Get the originating frame (failure is non-fatal) + // Get the originating frame nsGenericHTMLElement* originatingElement = nullptr; if (aEvent) { - InternalFormEvent* formEvent = aEvent->AsFormEvent(); - if (formEvent) { - nsIContent* originator = formEvent->mOriginator; - if (originator) { - if (!originator->IsHTMLElement()) { - return NS_ERROR_UNEXPECTED; - } - originatingElement = static_cast(originator); - } + SubmitEvent* submitEvent = aEvent->AsSubmitEvent(); + if (submitEvent) { + originatingElement = submitEvent->GetSubmitter(); } } diff --git a/dom/html/HTMLFormElement.h b/dom/html/HTMLFormElement.h index 4931561ea1ad..d247e988fc26 100644 --- a/dom/html/HTMLFormElement.h +++ b/dom/html/HTMLFormElement.h @@ -430,7 +430,6 @@ class HTMLFormElement final : public nsGenericHTMLElement, RefPtr mForm; }; - nsresult DoSubmitOrReset(WidgetEvent* aEvent, EventMessage aMessage); nsresult DoReset(); // Async callback to handle removal of our default submit @@ -442,12 +441,11 @@ class HTMLFormElement final : public nsGenericHTMLElement, // /** * Attempt to submit (submission might be deferred) - * (called by DoSubmitOrReset) * * @param aPresContext the presentation context * @param aEvent the DOM event that was passed to us for the submit */ - nsresult DoSubmit(WidgetEvent* aEvent); + nsresult DoSubmit(Event* aEvent = nullptr); /** * Prepare the submission object (called by DoSubmit) @@ -455,8 +453,7 @@ class HTMLFormElement final : public nsGenericHTMLElement, * @param aFormSubmission the submission object * @param aEvent the DOM event that was passed to us for the submit */ - nsresult BuildSubmission(HTMLFormSubmission** aFormSubmission, - WidgetEvent* aEvent); + nsresult BuildSubmission(HTMLFormSubmission** aFormSubmission, Event* aEvent); /** * Perform the submission (called by DoSubmit and FlushPendingSubmission) * diff --git a/dom/tests/mochitest/general/test_interfaces.js b/dom/tests/mochitest/general/test_interfaces.js index 1bcc19f2175f..3bc6c89e59c5 100644 --- a/dom/tests/mochitest/general/test_interfaces.js +++ b/dom/tests/mochitest/general/test_interfaces.js @@ -1052,6 +1052,8 @@ var interfaceNamesInGlobalScope = [ // IMPORTANT: Do not change this list without review from a DOM peer! { name: "SubtleCrypto", insecureContext: true }, // IMPORTANT: Do not change this list without review from a DOM peer! + { name: "SubmitEvent", insecureContext: true }, + // IMPORTANT: Do not change this list without review from a DOM peer! { name: "SVGAElement", insecureContext: true }, // IMPORTANT: Do not change this list without review from a DOM peer! { name: "SVGAngle", insecureContext: true }, diff --git a/dom/webidl/SubmitEvent.webidl b/dom/webidl/SubmitEvent.webidl new file mode 100644 index 000000000000..43507fe67592 --- /dev/null +++ b/dom/webidl/SubmitEvent.webidl @@ -0,0 +1,19 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * The origin of this IDL file is + * https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#submitevent + */ + +[Exposed=Window] +interface SubmitEvent : Event { + constructor(DOMString type, optional SubmitEventInit eventInitDict = {}); + + readonly attribute HTMLElement? submitter; +}; + +dictionary SubmitEventInit : EventInit { + HTMLElement? submitter = null; +}; diff --git a/dom/webidl/moz.build b/dom/webidl/moz.build index 6d26c622dac8..c88531f11420 100644 --- a/dom/webidl/moz.build +++ b/dom/webidl/moz.build @@ -1085,6 +1085,7 @@ GENERATED_EVENTS_WEBIDL_FILES = [ 'ScrollViewChangeEvent.webidl', 'SecurityPolicyViolationEvent.webidl', 'StyleSheetApplicableStateChangeEvent.webidl', + 'SubmitEvent.webidl', 'TCPServerSocketEvent.webidl', 'TCPSocketErrorEvent.webidl', 'TCPSocketEvent.webidl', diff --git a/testing/web-platform/meta/html/dom/idlharness.https.html.ini b/testing/web-platform/meta/html/dom/idlharness.https.html.ini index ea2e7e4b566b..40392eada053 100644 --- a/testing/web-platform/meta/html/dom/idlharness.https.html.ini +++ b/testing/web-platform/meta/html/dom/idlharness.https.html.ini @@ -723,28 +723,6 @@ prefs: [dom.security.featurePolicy.enabled:true, dom.security.featurePolicy.expe [FormDataEvent interface object length] expected: FAIL - [SubmitEvent interface: attribute submitter] - expected: FAIL - - [SubmitEvent interface: existence and properties of interface prototype object's @@unscopables property] - expected: FAIL - - [SubmitEvent interface object length] - expected: FAIL - - [SubmitEvent interface: existence and properties of interface prototype object] - expected: FAIL - - [SubmitEvent interface: existence and properties of interface object] - expected: FAIL - - [SubmitEvent interface: existence and properties of interface prototype object's "constructor" property] - expected: FAIL - - [SubmitEvent interface object name] - expected: FAIL - - [idlharness.https.html?include=(Document|Window)] [Document interface: documentWithHandlers must inherit property "onsecuritypolicyviolation" with the proper type] expected: FAIL diff --git a/testing/web-platform/meta/html/semantics/forms/form-submission-0/SubmitEvent.window.js.ini b/testing/web-platform/meta/html/semantics/forms/form-submission-0/SubmitEvent.window.js.ini deleted file mode 100644 index 7fb4436c2da2..000000000000 --- a/testing/web-platform/meta/html/semantics/forms/form-submission-0/SubmitEvent.window.js.ini +++ /dev/null @@ -1,19 +0,0 @@ -[SubmitEvent.window.html] - [Successful SubmitEvent constructor] - expected: FAIL - - [Failing SubmitEvent constructor] - expected: FAIL - - [Successful SubmitEvent constructor; empty dictionary] - expected: FAIL - - [Successful SubmitEvent constructor; missing dictionary] - expected: FAIL - - [Successful SubmitEvent constructor; null/undefined submitter] - expected: FAIL - - [Successful SubmitEvent constructor; null/undefined dictionary] - expected: FAIL - diff --git a/testing/web-platform/meta/html/semantics/forms/form-submission-0/form-submission-algorithm.html.ini b/testing/web-platform/meta/html/semantics/forms/form-submission-0/form-submission-algorithm.html.ini deleted file mode 100644 index 5bddbf98b2b6..000000000000 --- a/testing/web-platform/meta/html/semantics/forms/form-submission-0/form-submission-algorithm.html.ini +++ /dev/null @@ -1,13 +0,0 @@ -[form-submission-algorithm.html] - [firing an event named submit; form.requestSubmit(submitter)] - expected: FAIL - - [firing an event named submit; clicking a submit button] - expected: FAIL - - [firing an event named submit; form.requestSubmit(null)] - expected: FAIL - - [firing an event named submit; form.requestSubmit()] - expected: FAIL - diff --git a/testing/web-platform/meta/html/semantics/forms/form-submission-0/implicit-submission.optional.html.ini b/testing/web-platform/meta/html/semantics/forms/form-submission-0/implicit-submission.optional.html.ini index ab40bfddfdf2..03dbcf5c7edf 100644 --- a/testing/web-platform/meta/html/semantics/forms/form-submission-0/implicit-submission.optional.html.ini +++ b/testing/web-platform/meta/html/semantics/forms/form-submission-0/implicit-submission.optional.html.ini @@ -1,7 +1,3 @@ [implicit-submission.optional.html] [Submit event with a submit button] - expected: FAIL - - [Submit event with no submit button] - expected: FAIL - + expected: FAIL \ No newline at end of file