gecko-dev/dom/base/nsFormData.h
Nikhil Marathe f51e8c8dbd Bug 1127150 - Use File's name instead of explicit file name in form submission related classes. r=baku
Our nsFormSubmission and subclasses accepted a third filename argument to
explicitly specify the filename. Since switching from nsIDOMBlob to File in Bug
1085283, we can read out the filename directly from the File. This simplifies
the code, but introduces a change in the way Firefox submits form data to
servers.

Consider the code:
var fd = new FormData();
fd.append("blob1", new Blob(["hi"]), ""); // explicit empty filename as third arg
fd.append("file1", new File(["hi"], "")); // File's name is empty, no third arg.
xhr.send(fd);

Previously, the request body had filename="" in the first case, and filename="blob" in the second.
This patch will change it to both cases result in filename=""

This behaviour isn't exactly specced anywhere, nor in the HTML spec [1], nor in
RFC 2388. In addition Blink (at least Chromium v40) has the same behaviour
introduced by this patch. So shipping it seems ok to me.

[1]: http://www.w3.org/html/wg/drafts/html/master/semantics.html#multipart/form-data-encoding-algorithm

--HG--
extra : rebase_source : 6631e6900fe1a9b991c397b76e5be6b913715c5a
2015-02-21 11:54:44 -08:00

157 lines
4.7 KiB
C++

/* 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/. */
#ifndef nsFormData_h__
#define nsFormData_h__
#include "mozilla/Attributes.h"
#include "nsIDOMFormData.h"
#include "nsIXMLHttpRequest.h"
#include "nsFormSubmission.h"
#include "nsWrapperCache.h"
#include "nsTArray.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/dom/BindingDeclarations.h"
#include "mozilla/dom/FormDataBinding.h"
namespace mozilla {
class ErrorResult;
namespace dom {
class File;
class HTMLFormElement;
class GlobalObject;
} // namespace dom
} // namespace mozilla
class nsFormData MOZ_FINAL : public nsIDOMFormData,
public nsIXHRSendable,
public nsFormSubmission,
public nsWrapperCache
{
private:
~nsFormData() {}
typedef mozilla::dom::File File;
struct FormDataTuple
{
nsString name;
nsString stringValue;
nsRefPtr<File> fileValue;
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)
{
MOZ_ASSERT(aData);
aData->name = aName;
aData->fileValue = aBlob;
aData->valueIsFile = true;
}
void ExtractValue(const FormDataTuple& aTuple,
mozilla::dom::OwningFileOrUSVString* aOutValue);
public:
explicit nsFormData(nsISupports* aOwner = nullptr);
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(nsFormData,
nsIDOMFormData)
NS_DECL_NSIDOMFORMDATA
NS_DECL_NSIXHRSENDABLE
// nsWrapperCache
virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
// WebIDL
nsISupports*
GetParentObject() const
{
return mOwner;
}
static already_AddRefed<nsFormData>
Constructor(const mozilla::dom::GlobalObject& aGlobal,
const mozilla::dom::Optional<mozilla::dom::NonNull<mozilla::dom::HTMLFormElement> >& aFormElement,
mozilla::ErrorResult& aRv);
void Append(const nsAString& aName, const nsAString& aValue);
void Append(const nsAString& aName, File& aBlob,
const mozilla::dom::Optional<nsAString>& aFilename);
void Delete(const nsAString& aName);
void Get(const nsAString& aName, mozilla::dom::Nullable<mozilla::dom::OwningFileOrUSVString>& aOutValue);
void GetAll(const nsAString& aName, nsTArray<mozilla::dom::OwningFileOrUSVString>& aValues);
bool Has(const nsAString& aName);
void Set(const nsAString& aName, File& aBlob,
const mozilla::dom::Optional<nsAString>& aFilename);
void Set(const nsAString& aName, const nsAString& aValue);
// nsFormSubmission
virtual nsresult GetEncodedSubmission(nsIURI* aURI,
nsIInputStream** aPostDataStream) MOZ_OVERRIDE;
virtual nsresult AddNameValuePair(const nsAString& aName,
const nsAString& aValue) MOZ_OVERRIDE
{
FormDataTuple* data = mFormData.AppendElement();
SetNameValuePair(data, aName, aValue);
return NS_OK;
}
virtual nsresult AddNameFilePair(const nsAString& aName,
File* aBlob) MOZ_OVERRIDE
{
FormDataTuple* data = mFormData.AppendElement();
SetNameFilePair(data, aName, aBlob);
return NS_OK;
}
typedef bool (*FormDataEntryCallback)(const nsString& aName, bool aIsFile,
const nsString& aValue,
File* aFile, void* aClosure);
uint32_t
Length() const
{
return mFormData.Length();
}
// Stops iteration and returns false if any invocation of callback returns
// false. Returns true otherwise.
bool
ForEach(FormDataEntryCallback aFunc, void* aClosure)
{
for (uint32_t i = 0; i < mFormData.Length(); ++i) {
FormDataTuple& tuple = mFormData[i];
if (!aFunc(tuple.name, tuple.valueIsFile, tuple.stringValue,
tuple.fileValue, aClosure)) {
return false;
}
}
return true;
}
private:
nsCOMPtr<nsISupports> mOwner;
nsTArray<FormDataTuple> mFormData;
};
#endif // nsFormData_h__