Bug 1237595 - FormData ctor and form submission should create empty Blob/File when a input type=file is not set, r=smaug

This commit is contained in:
Andrea Marchesini 2016-01-08 08:35:30 +00:00
Родитель d7f8317f74
Коммит d64cfad447
7 изменённых файлов: 123 добавлений и 67 удалений

Просмотреть файл

@ -957,6 +957,32 @@ BlobImplFile::LookupAndCacheIsDirectory()
mDirState = isDir ? BlobDirState::eIsDir : BlobDirState::eIsNotDir; mDirState = isDir ? BlobDirState::eIsDir : BlobDirState::eIsNotDir;
} }
////////////////////////////////////////////////////////////////////////////
// BlobImplEmptyFile implementation
NS_IMPL_ISUPPORTS_INHERITED0(BlobImplEmptyFile, BlobImpl)
already_AddRefed<BlobImpl>
BlobImplEmptyFile::CreateSlice(uint64_t aStart, uint64_t aLength,
const nsAString& aContentType,
ErrorResult& aRv)
{
MOZ_ASSERT(!aStart && !aLength);
RefPtr<BlobImpl> impl = new BlobImplEmptyFile(aContentType);
return impl.forget();
}
void
BlobImplEmptyFile::GetInternalStream(nsIInputStream** aStream,
ErrorResult& aRv)
{
nsresult rv = NS_NewCStringInputStream(aStream, EmptyCString());
if (NS_WARN_IF(NS_FAILED(rv))) {
aRv.Throw(rv);
return;
}
}
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
// BlobImplMemory implementation // BlobImplMemory implementation

Просмотреть файл

@ -833,6 +833,31 @@ private:
bool mIsTemporary; bool mIsTemporary;
}; };
class BlobImplEmptyFile final : public BlobImplBase
{
public:
NS_DECL_ISUPPORTS_INHERITED
explicit BlobImplEmptyFile(const nsAString& aContentType)
: BlobImplBase(EmptyString(), aContentType, 0 /* aLength */)
{}
virtual void GetInternalStream(nsIInputStream** aStream,
ErrorResult& aRv) override;
virtual already_AddRefed<BlobImpl>
CreateSlice(uint64_t aStart, uint64_t aLength,
const nsAString& aContentType, ErrorResult& aRv) override;
virtual bool IsMemoryFile() const override
{
return true;
}
private:
~BlobImplEmptyFile() {}
};
} // namespace dom } // namespace dom
} // namespace mozilla } // namespace mozilla

Просмотреть файл

@ -179,6 +179,8 @@ FormData::Has(const nsAString& aName)
nsresult nsresult
FormData::AddNameFilePair(const nsAString& aName, File* aFile) FormData::AddNameFilePair(const nsAString& aName, File* aFile)
{ {
MOZ_ASSERT(aFile);
FormDataTuple* data = mFormData.AppendElement(); FormDataTuple* data = mFormData.AppendElement();
SetNameFilePair(data, aName, aFile); SetNameFilePair(data, aName, aFile);
return NS_OK; return NS_OK;
@ -272,12 +274,10 @@ FormData::SetNameFilePair(FormDataTuple* aData,
File* aFile) File* aFile)
{ {
MOZ_ASSERT(aData); MOZ_ASSERT(aData);
MOZ_ASSERT(aFile);
aData->name = aName; aData->name = aName;
if (aFile) {
aData->value.SetAsFile() = aFile; aData->value.SetAsFile() = aFile;
} else {
aData->value.SetAsUSVString() = EmptyString();
}
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
@ -364,7 +364,7 @@ FormData::GetSendInfo(nsIInputStream** aBody, uint64_t* aContentLength,
fs.AddNameValuePair(mFormData[i].name, fs.AddNameValuePair(mFormData[i].name,
mFormData[i].value.GetAsUSVString()); mFormData[i].value.GetAsUSVString());
} else { } else {
fs.AddNameFilePair(mFormData[i].name, nullptr); MOZ_CRASH("This should no be possible.");
} }
} }

Просмотреть файл

@ -14,7 +14,16 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=789315
<form id="a"><input name="b" type="file"/></form> <form id="a"><input name="b" type="file"/></form>
<script type="text/javascript"> <script type="text/javascript">
is(new FormData(document.getElementById('a')).get('b'), "", "This should return an empty string."); var obj = new FormData(document.getElementById('a')).get('b');
ok(obj instanceof File, "This should return an empty File");
is(obj.size, 0, "Size should be 0");
is(obj.name, "", "Name should be an empty string");
is(obj.type, "application/octet-stream", "Type should be application/octet-stream");
var o = obj.slice(10, 100, "foo/bar");
is(o.size, 0, "The new blob has size 0");
is(o.type, "foo/bar", "The new blob has type foo/bar");
</script> </script>
</body> </body>

Просмотреть файл

@ -5593,9 +5593,10 @@ HTMLInputElement::SubmitNamesValues(nsFormSubmission* aFormSubmission)
} }
if (files.IsEmpty()) { if (files.IsEmpty()) {
// If no file was selected, pretend we had an empty file with an RefPtr<BlobImpl> blobImpl =
// empty filename. new BlobImplEmptyFile(NS_LITERAL_STRING("application/octet-stream"));
aFormSubmission->AddNameFilePair(name, nullptr); RefPtr<File> file = File::Create(OwnerDoc()->GetInnerWindow(), blobImpl);
aFormSubmission->AddNameFilePair(name, file);
} }
return NS_OK; return NS_OK;

Просмотреть файл

@ -167,15 +167,15 @@ nsresult
nsFSURLEncoded::AddNameFilePair(const nsAString& aName, nsFSURLEncoded::AddNameFilePair(const nsAString& aName,
File* aFile) File* aFile)
{ {
MOZ_ASSERT(aFile);
if (!mWarnedFileControl) { if (!mWarnedFileControl) {
SendJSWarning(mDocument, "ForgotFileEnctypeWarning", nullptr, 0); SendJSWarning(mDocument, "ForgotFileEnctypeWarning", nullptr, 0);
mWarnedFileControl = true; mWarnedFileControl = true;
} }
nsAutoString filename; nsAutoString filename;
if (aFile) {
aFile->GetName(filename); aFile->GetName(filename);
}
return AddNameValuePair(aName, filename); return AddNameValuePair(aName, filename);
} }
@ -441,14 +441,13 @@ nsresult
nsFSMultipartFormData::AddNameFilePair(const nsAString& aName, nsFSMultipartFormData::AddNameFilePair(const nsAString& aName,
File* aFile) File* aFile)
{ {
MOZ_ASSERT(aFile);
// Encode the control name // Encode the control name
nsAutoCString nameStr; nsAutoCString nameStr;
nsresult rv = EncodeVal(aName, nameStr, true); nsresult rv = EncodeVal(aName, nameStr, true);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
nsCString filename, contentType;
nsCOMPtr<nsIInputStream> fileStream;
if (aFile) {
nsAutoString filename16; nsAutoString filename16;
aFile->GetName(filename16); aFile->GetName(filename16);
@ -464,6 +463,7 @@ nsFSMultipartFormData::AddNameFilePair(const nsAString& aName,
filename16 = filepath16 + filename16; filename16 = filepath16 + filename16;
} }
nsAutoCString filename;
rv = EncodeVal(filename16, filename, true); rv = EncodeVal(filename16, filename, true);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
@ -473,12 +473,15 @@ nsFSMultipartFormData::AddNameFilePair(const nsAString& aName,
if (contentType16.IsEmpty()) { if (contentType16.IsEmpty()) {
contentType16.AssignLiteral("application/octet-stream"); contentType16.AssignLiteral("application/octet-stream");
} }
nsAutoCString contentType;
contentType.Adopt(nsLinebreakConverter:: contentType.Adopt(nsLinebreakConverter::
ConvertLineBreaks(NS_ConvertUTF16toUTF8(contentType16).get(), ConvertLineBreaks(NS_ConvertUTF16toUTF8(contentType16).get(),
nsLinebreakConverter::eLinebreakAny, nsLinebreakConverter::eLinebreakAny,
nsLinebreakConverter::eLinebreakSpace)); nsLinebreakConverter::eLinebreakSpace));
// Get input stream // Get input stream
nsCOMPtr<nsIInputStream> fileStream;
aFile->GetInternalStream(getter_AddRefs(fileStream), error); aFile->GetInternalStream(getter_AddRefs(fileStream), error);
if (NS_WARN_IF(error.Failed())) { if (NS_WARN_IF(error.Failed())) {
return error.StealNSResult(); return error.StealNSResult();
@ -493,10 +496,6 @@ nsFSMultipartFormData::AddNameFilePair(const nsAString& aName,
fileStream = bufferedStream; fileStream = bufferedStream;
} }
}
else {
contentType.AssignLiteral("application/octet-stream");
}
// //
// Make MIME block for name/value pair // Make MIME block for name/value pair
@ -619,9 +618,7 @@ nsFSTextPlain::AddNameFilePair(const nsAString& aName,
File* aFile) File* aFile)
{ {
nsAutoString filename; nsAutoString filename;
if (aFile) {
aFile->GetName(filename); aFile->GetName(filename);
}
AddNameValuePair(aName, filename); AddNameValuePair(aName, filename);
return NS_OK; return NS_OK;

Просмотреть файл

@ -258,7 +258,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=523771
<p> <p>
File input: File input:
<input type=file name="file_1" class="setfile"> <input type=file name="file_1" class="setfile">
<input type=file name="file_2" class="setfile empty"> <input type=file name="file_2">
<input type=file name="" class="setfile"> <input type=file name="" class="setfile">
<input type=file name=""> <input type=file name="">
<input type=file class="setfile"> <input type=file class="setfile">
@ -268,7 +268,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=523771
Multifile input: Multifile input:
<input multiple type=file name="file_3" class="setfile"> <input multiple type=file name="file_3" class="setfile">
<input multiple type=file name="file_4" class="setfile multi"> <input multiple type=file name="file_4" class="setfile multi">
<input multiple type=file name="file_5" class="setfile empty"> <input multiple type=file name="file_5">
<input multiple type=file name="" class="setfile"> <input multiple type=file name="" class="setfile">
<input multiple type=file name="" class="setfile multi"> <input multiple type=file name="" class="setfile multi">
<input multiple type=file name=""> <input multiple type=file name="">
@ -426,7 +426,6 @@ function onFilesOpened(files) {
let singleFile = textFile; let singleFile = textFile;
let multiFile = [textFile, imageFile]; let multiFile = [textFile, imageFile];
emptyFile = new File([], "", { type: "application/octet-stream" });
var addList = document.getElementsByClassName("setfile"); var addList = document.getElementsByClassName("setfile");
let i = 0; let i = 0;
@ -434,8 +433,6 @@ function onFilesOpened(files) {
while (input = addList[i++]) { while (input = addList[i++]) {
if (input.classList.contains("multi")) { if (input.classList.contains("multi")) {
SpecialPowers.wrap(input).mozSetFileArray(multiFile); SpecialPowers.wrap(input).mozSetFileArray(multiFile);
} else if (input.classList.contains("empty")) {
SpecialPowers.wrap(input).mozSetFileArray([emptyFile]);
} else { } else {
SpecialPowers.wrap(input).mozSetFileArray([singleFile]); SpecialPowers.wrap(input).mozSetFileArray([singleFile]);
} }
@ -449,6 +446,7 @@ function onFilesOpened(files) {
myFile2 = input.files[1]; myFile2 = input.files[1];
is(myFile1.size, 20, "File1 size"); is(myFile1.size, 20, "File1 size");
is(myFile2.size, 2711, "File2 size"); is(myFile2.size, 2711, "File2 size");
emptyFile = { name: "", type: "application/octet-stream" };
// Now, actually run the tests; see below. // Now, actually run the tests; see below.
onFilesSet(); onFilesSet();