diff --git a/dom/base/nsFormData.cpp b/dom/base/nsFormData.cpp index b1fd0d85551..da486d2cc2d 100644 --- a/dom/base/nsFormData.cpp +++ b/dom/base/nsFormData.cpp @@ -6,9 +6,7 @@ #include "nsIVariant.h" #include "nsIInputStream.h" #include "mozilla/dom/File.h" -#include "mozilla/dom/File.h" #include "mozilla/dom/HTMLFormElement.h" -#include "mozilla/dom/FormDataBinding.h" using namespace mozilla; using namespace mozilla::dom; @@ -86,6 +84,119 @@ nsFormData::Append(const nsAString& aName, File& aBlob, AddNameFilePair(aName, &aBlob, filename); } +void +nsFormData::Delete(const nsAString& aName) +{ + // We have to use this slightly awkward for loop since uint32_t >= 0 is an + // error for being always true. + for (uint32_t i = mFormData.Length(); i-- > 0; ) { + if (aName.Equals(mFormData[i].name)) { + mFormData.RemoveElementAt(i); + } + } +} + +void +nsFormData::ExtractValue(const FormDataTuple& aTuple, + OwningFileOrUSVString* aOutValue) +{ + if (aTuple.valueIsFile) { + aOutValue->SetAsFile() = aTuple.fileValue; + } else { + aOutValue->SetAsUSVString() = aTuple.stringValue; + } +} + +void +nsFormData::Get(const nsAString& aName, + Nullable& aOutValue) +{ + for (uint32_t i = 0; i < mFormData.Length(); ++i) { + if (aName.Equals(mFormData[i].name)) { + ExtractValue(mFormData[i], &aOutValue.SetValue()); + return; + } + } + + aOutValue.SetNull(); +} + +void +nsFormData::GetAll(const nsAString& aName, + nsTArray& aValues) +{ + for (uint32_t i = 0; i < mFormData.Length(); ++i) { + if (aName.Equals(mFormData[i].name)) { + OwningFileOrUSVString* element = aValues.AppendElement(); + ExtractValue(mFormData[i], element); + } + } +} + +bool +nsFormData::Has(const nsAString& aName) +{ + for (uint32_t i = 0; i < mFormData.Length(); ++i) { + if (aName.Equals(mFormData[i].name)) { + return true; + } + } + + return false; +} + +nsFormData::FormDataTuple* +nsFormData::RemoveAllOthersAndGetFirstFormDataTuple(const nsAString& aName) +{ + FormDataTuple* lastFoundTuple = nullptr; + uint32_t lastFoundIndex = mFormData.Length(); + // We have to use this slightly awkward for loop since uint32_t >= 0 is an + // error for being always true. + for (uint32_t i = mFormData.Length(); i-- > 0; ) { + if (aName.Equals(mFormData[i].name)) { + if (lastFoundTuple) { + // The one we found earlier was not the first one, we can remove it. + mFormData.RemoveElementAt(lastFoundIndex); + } + + lastFoundTuple = &mFormData[i]; + lastFoundIndex = i; + } + } + + return lastFoundTuple; +} + +void +nsFormData::Set(const nsAString& aName, File& aBlob, + const Optional& aFilename) +{ + FormDataTuple* tuple = RemoveAllOthersAndGetFirstFormDataTuple(aName); + if (tuple) { + nsAutoString filename; + if (aFilename.WasPassed()) { + filename = aFilename.Value(); + } else { + filename.SetIsVoid(true); + } + + SetNameFilePair(tuple, aName, &aBlob, filename); + } else { + Append(aName, aBlob, aFilename); + } +} + +void +nsFormData::Set(const nsAString& aName, const nsAString& aValue) +{ + FormDataTuple* tuple = RemoveAllOthersAndGetFirstFormDataTuple(aName); + if (tuple) { + SetNameValuePair(tuple, aName, aValue); + } else { + Append(aName, aValue); + } +} + // ------------------------------------------------------------------------- // nsIDOMFormData diff --git a/dom/base/nsFormData.h b/dom/base/nsFormData.h index 64e6c4ee719..97021cfc795 100644 --- a/dom/base/nsFormData.h +++ b/dom/base/nsFormData.h @@ -13,6 +13,7 @@ #include "nsTArray.h" #include "mozilla/ErrorResult.h" #include "mozilla/dom/BindingDeclarations.h" +#include "mozilla/dom/FormDataBinding.h" namespace mozilla { class ErrorResult; @@ -29,8 +30,48 @@ class nsFormData MOZ_FINAL : public nsIDOMFormData, public nsFormSubmission, public nsWrapperCache { +private: ~nsFormData() {} + typedef mozilla::dom::File File; + struct FormDataTuple + { + nsString name; + nsString stringValue; + nsRefPtr fileValue; + nsString filename; + bool valueIsFile; + }; + + // Returns the FormDataTuple to modify. This may be null, in which case + // no element with aName was found. + FormDataTuple* + RemoveAllOthersAndGetFirstFormDataTuple(const nsAString& aName); + + void SetNameValuePair(FormDataTuple* aData, + const nsAString& aName, + const nsAString& aValue) + { + MOZ_ASSERT(aData); + aData->name = aName; + aData->stringValue = aValue; + aData->valueIsFile = false; + } + + void SetNameFilePair(FormDataTuple* aData, + const nsAString& aName, + File* aBlob, + const nsAString& aFilename) + { + MOZ_ASSERT(aData); + aData->name = aName; + aData->fileValue = aBlob; + aData->filename = aFilename; + aData->valueIsFile = true; + } + + void ExtractValue(const FormDataTuple& aTuple, + mozilla::dom::OwningFileOrUSVString* aOutValue); public: explicit nsFormData(nsISupports* aOwner = nullptr); @@ -55,8 +96,15 @@ public: const mozilla::dom::Optional >& aFormElement, mozilla::ErrorResult& aRv); void Append(const nsAString& aName, const nsAString& aValue); - void Append(const nsAString& aName, mozilla::dom::File& aBlob, + void Append(const nsAString& aName, File& aBlob, const mozilla::dom::Optional& aFilename); + void Delete(const nsAString& aName); + void Get(const nsAString& aName, mozilla::dom::Nullable& aOutValue); + void GetAll(const nsAString& aName, nsTArray& aValues); + bool Has(const nsAString& aName); + void Set(const nsAString& aName, File& aBlob, + const mozilla::dom::Optional& aFilename); + void Set(const nsAString& aName, const nsAString& aValue); // nsFormSubmission virtual nsresult GetEncodedSubmission(nsIURI* aURI, @@ -65,35 +113,20 @@ public: const nsAString& aValue) MOZ_OVERRIDE { FormDataTuple* data = mFormData.AppendElement(); - data->name = aName; - data->stringValue = aValue; - data->valueIsFile = false; + SetNameValuePair(data, aName, aValue); return NS_OK; } virtual nsresult AddNameFilePair(const nsAString& aName, - nsIDOMBlob* aBlob, + File* aBlob, const nsString& aFilename) MOZ_OVERRIDE { FormDataTuple* data = mFormData.AppendElement(); - data->name = aName; - data->fileValue = aBlob; - data->filename = aFilename; - data->valueIsFile = true; + SetNameFilePair(data, aName, aBlob, aFilename); return NS_OK; } - private: nsCOMPtr mOwner; - struct FormDataTuple - { - nsString name; - nsString stringValue; - nsCOMPtr fileValue; - nsString filename; - bool valueIsFile; - }; - nsTArray mFormData; }; diff --git a/dom/html/nsFormSubmission.cpp b/dom/html/nsFormSubmission.cpp index 24336b7fcf4..984b7d8d395 100644 --- a/dom/html/nsFormSubmission.cpp +++ b/dom/html/nsFormSubmission.cpp @@ -38,6 +38,7 @@ #include "nsContentUtils.h" #include "mozilla/dom/EncodingUtils.h" +#include "mozilla/dom/File.h" using namespace mozilla; using mozilla::dom::EncodingUtils; @@ -78,7 +79,7 @@ public: virtual nsresult AddNameValuePair(const nsAString& aName, const nsAString& aValue); virtual nsresult AddNameFilePair(const nsAString& aName, - nsIDOMBlob* aBlob, + File* aBlob, const nsString& aFilename); virtual nsresult GetEncodedSubmission(nsIURI* aURI, nsIInputStream** aPostDataStream); @@ -165,7 +166,7 @@ nsFSURLEncoded::AddIsindex(const nsAString& aValue) nsresult nsFSURLEncoded::AddNameFilePair(const nsAString& aName, - nsIDOMBlob* aBlob, + File* aBlob, const nsString& aFilename) { if (!mWarnedFileControl) { @@ -174,9 +175,8 @@ nsFSURLEncoded::AddNameFilePair(const nsAString& aName, } nsAutoString filename; - nsCOMPtr file = do_QueryInterface(aBlob); - if (file) { - file->GetName(filename); + if (aBlob && aBlob->IsFile()) { + aBlob->GetName(filename); } return AddNameValuePair(aName, filename); @@ -441,7 +441,7 @@ nsFSMultipartFormData::AddNameValuePair(const nsAString& aName, nsresult nsFSMultipartFormData::AddNameFilePair(const nsAString& aName, - nsIDOMBlob* aBlob, + File* aBlob, const nsString& aFilename) { // Encode the control name @@ -459,9 +459,8 @@ nsFSMultipartFormData::AddNameFilePair(const nsAString& aName, } else { // Get and encode the filename nsAutoString filename16; - nsCOMPtr file = do_QueryInterface(aBlob); - if (file) { - rv = file->GetName(filename16); + if (aBlob->IsFile()) { + rv = aBlob->GetName(filename16); NS_ENSURE_SUCCESS(rv, rv); } @@ -469,7 +468,7 @@ nsFSMultipartFormData::AddNameFilePair(const nsAString& aName, filename16.AssignLiteral("blob"); } else { nsAutoString filepath16; - rv = file->GetPath(filepath16); + rv = aBlob->GetPath(filepath16); NS_ENSURE_SUCCESS(rv, rv); if (!filepath16.IsEmpty()) { // File.path includes trailing "/" @@ -598,7 +597,7 @@ public: virtual nsresult AddNameValuePair(const nsAString& aName, const nsAString& aValue); virtual nsresult AddNameFilePair(const nsAString& aName, - nsIDOMBlob* aBlob, + File* aBlob, const nsString& aFilename); virtual nsresult GetEncodedSubmission(nsIURI* aURI, nsIInputStream** aPostDataStream); @@ -622,13 +621,12 @@ nsFSTextPlain::AddNameValuePair(const nsAString& aName, nsresult nsFSTextPlain::AddNameFilePair(const nsAString& aName, - nsIDOMBlob* aBlob, + File* aBlob, const nsString& aFilename) { nsAutoString filename; - nsCOMPtr file = do_QueryInterface(aBlob); - if (file) { - file->GetName(filename); + if (aBlob && aBlob->IsFile()) { + aBlob->GetName(filename); } AddNameValuePair(aName, filename); diff --git a/dom/html/nsFormSubmission.h b/dom/html/nsFormSubmission.h index 27802f0fb94..d7b5e0d329c 100644 --- a/dom/html/nsFormSubmission.h +++ b/dom/html/nsFormSubmission.h @@ -20,7 +20,12 @@ class nsIDocShell; class nsIRequest; class nsISaveAsCharset; class nsIMultiplexInputStream; -class nsIDOMBlob; + +namespace mozilla { +namespace dom { +class File; +} // namespace dom +} // namespace mozilla /** * Class for form submissions; encompasses the function to call to submit as @@ -51,9 +56,9 @@ public: * @param aFilename the filename to be used (not void) */ virtual nsresult AddNameFilePair(const nsAString& aName, - nsIDOMBlob* aBlob, + mozilla::dom::File* aBlob, const nsString& aFilename) = 0; - + /** * Reports whether the instance supports AddIsindex(). * @@ -161,7 +166,7 @@ public: virtual nsresult AddNameValuePair(const nsAString& aName, const nsAString& aValue) MOZ_OVERRIDE; virtual nsresult AddNameFilePair(const nsAString& aName, - nsIDOMBlob* aBlob, + mozilla::dom::File* aBlob, const nsString& aFilename) MOZ_OVERRIDE; virtual nsresult GetEncodedSubmission(nsIURI* aURI, nsIInputStream** aPostDataStream) MOZ_OVERRIDE; diff --git a/dom/html/test/test_formData.html b/dom/html/test/test_formData.html index 9248debd9e4..f39c940b0a5 100644 --- a/dom/html/test/test_formData.html +++ b/dom/html/test/test_formData.html @@ -14,7 +14,90 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=690659 diff --git a/dom/webidl/FormData.webidl b/dom/webidl/FormData.webidl index 4e4bef26850..1003cc06688 100644 --- a/dom/webidl/FormData.webidl +++ b/dom/webidl/FormData.webidl @@ -7,8 +7,17 @@ * http://xhr.spec.whatwg.org */ +typedef (File or USVString) FormDataEntryValue; + [Constructor(optional HTMLFormElement form)] interface FormData { - void append(DOMString name, Blob value, optional DOMString filename); - void append(DOMString name, DOMString value); + void append(USVString name, Blob value, optional USVString filename); + void append(USVString name, USVString value); + void delete(USVString name); + FormDataEntryValue? get(USVString name); + sequence getAll(USVString name); + boolean has(USVString name); + void set(USVString name, Blob value, optional USVString filename); + void set(USVString name, USVString value); + // iterable; - Bug 1127703 };