зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
d7f8317f74
Коммит
d64cfad447
|
@ -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();
|
||||||
|
|
Загрузка…
Ссылка в новой задаче