Bug 1518442 - Part 2: Implement Event-based form participation; r=smaug,edgar
For Event-based form participation specification PR: https://github.com/whatwg/html/pull/4239 Differential Revision: https://phabricator.services.mozilla.com/D43986
This commit is contained in:
@@ -39,6 +39,7 @@
|
||||
// form submission
|
||||
#include "HTMLFormSubmissionConstants.h"
|
||||
#include "mozilla/dom/FormData.h"
|
||||
#include "mozilla/dom/FormDataEvent.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
#include "nsIFormSubmitObserver.h"
|
||||
#include "nsIObserverService.h"
|
||||
@@ -117,7 +118,8 @@ HTMLFormElement::HTMLFormElement(
|
||||
mDeferSubmission(false),
|
||||
mNotifiedObservers(false),
|
||||
mNotifiedObserversResult(false),
|
||||
mEverTriedInvalidSubmit(false) {
|
||||
mEverTriedInvalidSubmit(false),
|
||||
mIsConstructingEntryList(false) {
|
||||
// We start out valid.
|
||||
AddStatesSilently(NS_EVENT_STATE_VALID);
|
||||
}
|
||||
@@ -504,7 +506,8 @@ nsresult HTMLFormElement::DoSubmitOrReset(WidgetEvent* aEvent,
|
||||
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 (!doc || (doc->GetSandboxFlags() & SANDBOXED_FORMS)) {
|
||||
if (mIsConstructingEntryList || !doc ||
|
||||
(doc->GetSandboxFlags() & SANDBOXED_FORMS)) {
|
||||
return NS_OK;
|
||||
}
|
||||
return DoSubmit(aEvent);
|
||||
@@ -555,6 +558,13 @@ nsresult HTMLFormElement::DoSubmit(WidgetEvent* aEvent) {
|
||||
// prepare the submission object
|
||||
//
|
||||
nsresult rv = BuildSubmission(getter_Transfers(submission), aEvent);
|
||||
|
||||
// Don't raise an error if form cannot navigate.
|
||||
if (rv == NS_ERROR_NOT_AVAILABLE) {
|
||||
mIsSubmitting = false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
mIsSubmitting = false;
|
||||
return rv;
|
||||
@@ -606,17 +616,33 @@ nsresult HTMLFormElement::BuildSubmission(HTMLFormSubmission** aFormSubmission,
|
||||
|
||||
nsresult rv;
|
||||
|
||||
//
|
||||
// Walk over the form elements and call SubmitNamesValues() on them to get
|
||||
// their data.
|
||||
//
|
||||
auto encoding = GetSubmitEncoding()->OutputEncoding();
|
||||
RefPtr<FormData> formData =
|
||||
new FormData(GetOwnerGlobal(), encoding, originatingElement);
|
||||
rv = ConstructEntryList(formData);
|
||||
NS_ENSURE_SUBMIT_SUCCESS(rv);
|
||||
|
||||
// Step 9. If form cannot navigate, then return.
|
||||
// https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#form-submission-algorithm
|
||||
if (!GetComposedDoc()) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
//
|
||||
// Get the submission object
|
||||
//
|
||||
rv = HTMLFormSubmission::GetFromForm(this, originatingElement,
|
||||
rv = HTMLFormSubmission::GetFromForm(this, originatingElement, encoding,
|
||||
aFormSubmission);
|
||||
NS_ENSURE_SUBMIT_SUCCESS(rv);
|
||||
|
||||
//
|
||||
// Dump the data into the submission object
|
||||
//
|
||||
rv = WalkFormElements(*aFormSubmission);
|
||||
rv = formData->CopySubmissionDataTo(*aFormSubmission);
|
||||
NS_ENSURE_SUBMIT_SUCCESS(rv);
|
||||
|
||||
return NS_OK;
|
||||
@@ -857,8 +883,15 @@ nsresult HTMLFormElement::NotifySubmitObservers(nsIURI* aActionURL,
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult HTMLFormElement::WalkFormElements(
|
||||
HTMLFormSubmission* aFormSubmission) {
|
||||
nsresult HTMLFormElement::ConstructEntryList(FormData* aFormData) {
|
||||
MOZ_ASSERT(aFormData, "Must have FormData!");
|
||||
if (mIsConstructingEntryList) {
|
||||
// Step 2.2 of https://xhr.spec.whatwg.org/#dom-formdata.
|
||||
return NS_ERROR_DOM_INVALID_STATE_ERR;
|
||||
}
|
||||
|
||||
AutoRestore<bool> resetConstructingEntryList(mIsConstructingEntryList);
|
||||
mIsConstructingEntryList = true;
|
||||
// This shouldn't be called recursively, so use a rather large value
|
||||
// for the preallocated buffer.
|
||||
AutoTArray<RefPtr<nsGenericHTMLFormElement>, 100> sortedControls;
|
||||
@@ -872,12 +905,56 @@ nsresult HTMLFormElement::WalkFormElements(
|
||||
//
|
||||
for (uint32_t i = 0; i < len; ++i) {
|
||||
// Tell the control to submit its name/value pairs to the submission
|
||||
sortedControls[i]->SubmitNamesValues(aFormSubmission);
|
||||
sortedControls[i]->SubmitNamesValues(aFormData);
|
||||
}
|
||||
|
||||
FormDataEventInit init;
|
||||
init.mBubbles = true;
|
||||
init.mCancelable = false;
|
||||
init.mFormData = aFormData;
|
||||
RefPtr<FormDataEvent> event =
|
||||
FormDataEvent::Constructor(this, NS_LITERAL_STRING("formdata"), init);
|
||||
event->SetTrusted(true);
|
||||
|
||||
EventDispatcher::DispatchDOMEvent(ToSupports(this), nullptr, event, nullptr,
|
||||
nullptr);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NotNull<const Encoding*> HTMLFormElement::GetSubmitEncoding() {
|
||||
nsAutoString acceptCharsetValue;
|
||||
GetAttr(kNameSpaceID_None, nsGkAtoms::acceptcharset, acceptCharsetValue);
|
||||
|
||||
int32_t charsetLen = acceptCharsetValue.Length();
|
||||
if (charsetLen > 0) {
|
||||
int32_t offset = 0;
|
||||
int32_t spPos = 0;
|
||||
// get charset from charsets one by one
|
||||
do {
|
||||
spPos = acceptCharsetValue.FindChar(char16_t(' '), offset);
|
||||
int32_t cnt = ((-1 == spPos) ? (charsetLen - offset) : (spPos - offset));
|
||||
if (cnt > 0) {
|
||||
nsAutoString uCharset;
|
||||
acceptCharsetValue.Mid(uCharset, offset, cnt);
|
||||
|
||||
auto encoding = Encoding::ForLabelNoReplacement(uCharset);
|
||||
if (encoding) {
|
||||
return WrapNotNull(encoding);
|
||||
}
|
||||
}
|
||||
offset = spPos + 1;
|
||||
} while (spPos != -1);
|
||||
}
|
||||
// if there are no accept-charset or all the charset are not supported
|
||||
// Get the charset from document
|
||||
Document* doc = GetComposedDoc();
|
||||
if (doc) {
|
||||
return doc->GetDocumentCharacterSet();
|
||||
}
|
||||
return UTF_8_ENCODING;
|
||||
}
|
||||
|
||||
// nsIForm
|
||||
|
||||
NS_IMETHODIMP_(uint32_t)
|
||||
|
||||
Reference in New Issue
Block a user