Skip to content

Commit

Permalink
Bug 1518442 - Part 2: Implement Event-based form participation; r=sma…
Browse files Browse the repository at this point in the history
…ug,edgar

For Event-based form participation specification PR:
whatwg/html#4239

Differential Revision: https://phabricator.services.mozilla.com/D43986

UltraBlame original commit: 1ac7b20bb1d8c5528211fdba0246f7659bff3a7c
  • Loading branch information
marco-c committed Oct 4, 2019
1 parent f247d40 commit faa5f33
Show file tree
Hide file tree
Showing 6 changed files with 149 additions and 67 deletions.
62 changes: 46 additions & 16 deletions dom/base/FormData.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,19 @@
using namespace mozilla;
using namespace mozilla::dom;

FormData::FormData(nsISupports* aOwner)
: HTMLFormSubmission(nullptr, EmptyString(), UTF_8_ENCODING, nullptr),
FormData::FormData(nsISupports* aOwner, NotNull<const Encoding*> aEncoding,
Element* aOriginatingElement)
: HTMLFormSubmission(nullptr, EmptyString(), aEncoding,
aOriginatingElement),
mOwner(aOwner) {}

FormData::FormData(const FormData& aFormData)
: HTMLFormSubmission(aFormData.mActionURL, aFormData.mTarget,
aFormData.mEncoding, aFormData.mOriginatingElement) {
mOwner = aFormData.mOwner;
mFormData = aFormData.mFormData;
}

namespace {

already_AddRefed<File> GetOrCreateFileCalledBlob(Blob& aBlob,
Expand Down Expand Up @@ -290,8 +299,16 @@ already_AddRefed<FormData> FormData::Constructor(
const Optional<NonNull<HTMLFormElement> >& aFormElement, ErrorResult& aRv) {
RefPtr<FormData> formData = new FormData(aGlobal.GetAsSupports());
if (aFormElement.WasPassed()) {
aRv = aFormElement.Value().WalkFormElements(formData);
aRv = aFormElement.Value().ConstructEntryList(formData);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}



formData = formData->Clone();
}

return formData.forget();
}

Expand All @@ -302,28 +319,41 @@ nsresult FormData::GetSendInfo(nsIInputStream** aBody, uint64_t* aContentLength,
nsACString& aContentTypeWithCharset,
nsACString& aCharset) const {
FSMultipartFormData fs(nullptr, EmptyString(), UTF_8_ENCODING, nullptr);
nsresult rv = CopySubmissionDataTo(&fs);
NS_ENSURE_SUCCESS(rv, rv);

for (uint32_t i = 0; i < mFormData.Length(); ++i) {
fs.GetContentType(aContentTypeWithCharset);
aCharset.Truncate();
*aContentLength = 0;
NS_ADDREF(*aBody = fs.GetSubmissionBody(aContentLength));

return NS_OK;
}

already_AddRefed<FormData> FormData::Clone() {
RefPtr<FormData> formData = new FormData(*this);
return formData.forget();
}

nsresult FormData::CopySubmissionDataTo(
HTMLFormSubmission* aFormSubmission) const {
MOZ_ASSERT(aFormSubmission, "Must have FormSubmission!");
for (size_t i = 0; i < mFormData.Length(); ++i) {
if (mFormData[i].wasNullBlob) {
MOZ_ASSERT(mFormData[i].value.IsUSVString());
fs.AddNameBlobOrNullPair(mFormData[i].name, nullptr);
aFormSubmission->AddNameBlobOrNullPair(mFormData[i].name, nullptr);
} else if (mFormData[i].value.IsUSVString()) {
fs.AddNameValuePair(mFormData[i].name,
mFormData[i].value.GetAsUSVString());
aFormSubmission->AddNameValuePair(mFormData[i].name,
mFormData[i].value.GetAsUSVString());
} else if (mFormData[i].value.IsBlob()) {
fs.AddNameBlobOrNullPair(mFormData[i].name,
mFormData[i].value.GetAsBlob());
aFormSubmission->AddNameBlobOrNullPair(mFormData[i].name,
mFormData[i].value.GetAsBlob());
} else {
MOZ_ASSERT(mFormData[i].value.IsDirectory());
fs.AddNameDirectoryPair(mFormData[i].name,
mFormData[i].value.GetAsDirectory());
aFormSubmission->AddNameDirectoryPair(
mFormData[i].name, mFormData[i].value.GetAsDirectory());
}
}

fs.GetContentType(aContentTypeWithCharset);
aCharset.Truncate();
*aContentLength = 0;
NS_ADDREF(*aBody = fs.GetSubmissionBody(aContentLength));

return NS_OK;
}
9 changes: 8 additions & 1 deletion dom/base/FormData.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class FormData final : public nsISupports,
public HTMLFormSubmission,
public nsWrapperCache {
private:
FormData(const FormData& aFormData);
~FormData() {}

struct FormDataTuple {
Expand All @@ -49,7 +50,11 @@ class FormData final : public nsISupports,
Directory* aDirectory);

public:
explicit FormData(nsISupports* aOwner = nullptr);
explicit FormData(nsISupports* aOwner = nullptr,
NotNull<const Encoding*> aEncoding = UTF_8_ENCODING,
Element* aOriginatingElement = nullptr);

already_AddRefed<FormData> Clone();

NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(FormData)
Expand Down Expand Up @@ -136,6 +141,8 @@ class FormData final : public nsISupports,
nsACString& aContentTypeWithCharset,
nsACString& aCharset) const;

nsresult CopySubmissionDataTo(HTMLFormSubmission* aFormSubmission) const;

private:
nsCOMPtr<nsISupports> mOwner;

Expand Down
91 changes: 84 additions & 7 deletions dom/html/HTMLFormElement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@

#include "HTMLFormSubmissionConstants.h"
#include "mozilla/dom/FormData.h"
#include "mozilla/dom/FormDataEvent.h"
#include "mozilla/Telemetry.h"
#include "nsIFormSubmitObserver.h"
#include "nsIObserverService.h"
Expand Down Expand Up @@ -117,7 +118,8 @@ HTMLFormElement::HTMLFormElement(
mDeferSubmission(false),
mNotifiedObservers(false),
mNotifiedObserversResult(false),
mEverTriedInvalidSubmit(false) {
mEverTriedInvalidSubmit(false),
mIsConstructingEntryList(false) {

AddStatesSilently(NS_EVENT_STATE_VALID);
}
Expand Down Expand Up @@ -504,7 +506,8 @@ nsresult HTMLFormElement::DoSubmitOrReset(WidgetEvent* aEvent,
if (eFormSubmit == aMessage) {


if (!doc || (doc->GetSandboxFlags() & SANDBOXED_FORMS)) {
if (mIsConstructingEntryList || !doc ||
(doc->GetSandboxFlags() & SANDBOXED_FORMS)) {
return NS_OK;
}
return DoSubmit(aEvent);
Expand Down Expand Up @@ -555,6 +558,13 @@ nsresult HTMLFormElement::DoSubmit(WidgetEvent* aEvent) {


nsresult rv = BuildSubmission(getter_Transfers(submission), aEvent);


if (rv == NS_ERROR_NOT_AVAILABLE) {
mIsSubmitting = false;
return NS_OK;
}

if (NS_FAILED(rv)) {
mIsSubmitting = false;
return rv;
Expand Down Expand Up @@ -609,14 +619,30 @@ nsresult HTMLFormElement::BuildSubmission(HTMLFormSubmission** aFormSubmission,



rv = HTMLFormSubmission::GetFromForm(this, originatingElement,

auto encoding = GetSubmitEncoding()->OutputEncoding();
RefPtr<FormData> formData =
new FormData(GetOwnerGlobal(), encoding, originatingElement);
rv = ConstructEntryList(formData);
NS_ENSURE_SUBMIT_SUCCESS(rv);



if (!GetComposedDoc()) {
return NS_ERROR_NOT_AVAILABLE;
}




rv = HTMLFormSubmission::GetFromForm(this, originatingElement, encoding,
aFormSubmission);
NS_ENSURE_SUBMIT_SUCCESS(rv);




rv = WalkFormElements(*aFormSubmission);
rv = formData->CopySubmissionDataTo(*aFormSubmission);
NS_ENSURE_SUBMIT_SUCCESS(rv);

return NS_OK;
Expand Down Expand Up @@ -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) {

return NS_ERROR_DOM_INVALID_STATE_ERR;
}

AutoRestore<bool> resetConstructingEntryList(mIsConstructingEntryList);
mIsConstructingEntryList = true;


AutoTArray<RefPtr<nsGenericHTMLFormElement>, 100> sortedControls;
Expand All @@ -872,12 +905,56 @@ nsresult HTMLFormElement::WalkFormElements(

for (uint32_t i = 0; i < len; ++i) {

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;

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);
}


Document* doc = GetComposedDoc();
if (doc) {
return doc->GetDocumentCharacterSet();
}
return UTF_8_ENCODING;
}



NS_IMETHODIMP_(uint32_t)
Expand Down
8 changes: 6 additions & 2 deletions dom/html/HTMLFormElement.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@

#include "mozilla/AsyncEventDispatcher.h"
#include "mozilla/Attributes.h"
#include "mozilla/dom/HTMLFormSubmission.h"
#include "nsAutoPtr.h"
#include "nsCOMPtr.h"
#include "nsIForm.h"
Expand All @@ -33,6 +32,7 @@ class EventChainPreVisitor;
namespace dom {
class HTMLFormControlsCollection;
class HTMLImageElement;
class FormData;

class HTMLFormElement final : public nsGenericHTMLElement,
public nsIWebProgressListener,
Expand Down Expand Up @@ -282,7 +282,8 @@ class HTMLFormElement final : public nsGenericHTMLElement,



nsresult WalkFormElements(HTMLFormSubmission* aFormSubmission);

nsresult ConstructEntryList(FormData* aFormData);



Expand Down Expand Up @@ -611,8 +612,11 @@ class HTMLFormElement final : public nsGenericHTMLElement,


bool mEverTriedInvalidSubmit;

bool mIsConstructingEntryList;

private:
NotNull<const Encoding*> GetSubmitEncoding();
~HTMLFormElement();
};

Expand Down
45 changes: 4 additions & 41 deletions dom/html/HTMLFormSubmission.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -755,40 +755,6 @@ nsresult EncodingFormSubmission::EncodeVal(const nsAString& aStr,

namespace {

NotNull<const Encoding*> GetSubmitEncoding(nsGenericHTMLElement* aForm) {
nsAutoString acceptCharsetValue;
aForm->GetAttr(kNameSpaceID_None, nsGkAtoms::acceptcharset,
acceptCharsetValue);

int32_t charsetLen = acceptCharsetValue.Length();
if (charsetLen > 0) {
int32_t offset = 0;
int32_t spPos = 0;

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);
}


Document* doc = aForm->GetComposedDoc();
if (doc) {
return doc->GetDocumentCharacterSet();
}
return UTF_8_ENCODING;
}

void GetEnumAttr(nsGenericHTMLElement* aContent, nsAtom* atom,
int32_t* aValue) {
const nsAttrValue* value = aContent->GetParsedAttr(atom);
Expand All @@ -802,7 +768,7 @@ void GetEnumAttr(nsGenericHTMLElement* aContent, nsAtom* atom,

nsresult HTMLFormSubmission::GetFromForm(
HTMLFormElement* aForm, nsGenericHTMLElement* aOriginatingElement,
HTMLFormSubmission** aFormSubmission) {
NotNull<const Encoding*>& aEncoding, HTMLFormSubmission** aFormSubmission) {

NS_ASSERTION(aForm->GetComposedDoc(),
"Should have doc if we're building submission!");
Expand Down Expand Up @@ -866,16 +832,13 @@ nsresult HTMLFormSubmission::GetFromForm(
}


auto encoding = GetSubmitEncoding(aForm)->OutputEncoding();


if (method == NS_FORM_METHOD_POST && enctype == NS_FORM_ENCTYPE_MULTIPART) {
*aFormSubmission = new FSMultipartFormData(actionURL, target, encoding,
*aFormSubmission = new FSMultipartFormData(actionURL, target, aEncoding,
aOriginatingElement);
} else if (method == NS_FORM_METHOD_POST &&
enctype == NS_FORM_ENCTYPE_TEXTPLAIN) {
*aFormSubmission =
new FSTextPlain(actionURL, target, encoding, aOriginatingElement);
new FSTextPlain(actionURL, target, aEncoding, aOriginatingElement);
} else {
Document* doc = aForm->OwnerDoc();
if (enctype == NS_FORM_ENCTYPE_MULTIPART ||
Expand All @@ -893,7 +856,7 @@ nsresult HTMLFormSubmission::GetFromForm(

SendJSWarning(doc, "ForgotPostWarning", args);
}
*aFormSubmission = new FSURLEncoded(actionURL, target, encoding, method,
*aFormSubmission = new FSURLEncoded(actionURL, target, aEncoding, method,
doc, aOriginatingElement);
}

Expand Down
1 change: 1 addition & 0 deletions dom/html/HTMLFormSubmission.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ class HTMLFormSubmission {

static nsresult GetFromForm(HTMLFormElement* aForm,
nsGenericHTMLElement* aOriginatingElement,
NotNull<const Encoding*>& aEncoding,
HTMLFormSubmission** aFormSubmission);

virtual ~HTMLFormSubmission() { MOZ_COUNT_DTOR(HTMLFormSubmission); }
Expand Down

0 comments on commit faa5f33

Please sign in to comment.