--- a/dom/base/File.cpp
+++ b/dom/base/File.cpp
@@ -953,33 +953,33 @@ BlobImplFile::LookupAndCacheIsDirectory(
"This should only be called when this object has been created "
"from an nsIFile to note that the nsIFile is a directory");
bool isDir;
mFile->IsDirectory(&isDir);
mDirState = isDir ? BlobDirState::eIsDir : BlobDirState::eIsNotDir;
}
////////////////////////////////////////////////////////////////////////////
-// BlobImplEmptyFile implementation
+// EmptyBlobImpl implementation
-NS_IMPL_ISUPPORTS_INHERITED0(BlobImplEmptyFile, BlobImpl)
+NS_IMPL_ISUPPORTS_INHERITED0(EmptyBlobImpl, BlobImpl)
already_AddRefed<BlobImpl>
-BlobImplEmptyFile::CreateSlice(uint64_t aStart, uint64_t aLength,
- const nsAString& aContentType,
- ErrorResult& aRv)
+EmptyBlobImpl::CreateSlice(uint64_t aStart, uint64_t aLength,
+ const nsAString& aContentType,
+ ErrorResult& aRv)
{
MOZ_ASSERT(!aStart && !aLength);
- RefPtr<BlobImpl> impl = new BlobImplEmptyFile(aContentType);
+ RefPtr<BlobImpl> impl = new EmptyBlobImpl(aContentType);
return impl.forget();
}
void
-BlobImplEmptyFile::GetInternalStream(nsIInputStream** aStream,
- ErrorResult& aRv)
+EmptyBlobImpl::GetInternalStream(nsIInputStream** aStream,
+ ErrorResult& aRv)
{
nsresult rv = NS_NewCStringInputStream(aStream, EmptyCString());
if (NS_WARN_IF(NS_FAILED(rv))) {
aRv.Throw(rv);
return;
}
}
--- a/dom/base/File.h
+++ b/dom/base/File.h
@@ -65,16 +65,17 @@ class Blob : public nsIDOMBlob
public:
NS_DECL_NSIDOMBLOB
NS_DECL_NSIXHRSENDABLE
NS_DECL_NSIMUTABLE
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(Blob, nsIDOMBlob)
+ // This creates a Blob or a File based on the type of BlobImpl.
static Blob*
Create(nsISupports* aParent, BlobImpl* aImpl);
static already_AddRefed<Blob>
Create(nsISupports* aParent, const nsAString& aContentType,
uint64_t aLength);
static already_AddRefed<Blob>
@@ -828,37 +829,37 @@ private:
CreateSlice(uint64_t aStart, uint64_t aLength,
const nsAString& aContentType, ErrorResult& aRv) override;
nsCOMPtr<nsIFile> mFile;
bool mWholeFile;
bool mIsTemporary;
};
-class BlobImplEmptyFile final : public BlobImplBase
+class EmptyBlobImpl final : public BlobImplBase
{
public:
NS_DECL_ISUPPORTS_INHERITED
- explicit BlobImplEmptyFile(const nsAString& aContentType)
- : BlobImplBase(EmptyString(), aContentType, 0 /* aLength */)
+ explicit EmptyBlobImpl(const nsAString& aContentType)
+ : BlobImplBase(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() {}
+ ~EmptyBlobImpl() {}
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_File_h
--- a/dom/base/FormData.cpp
+++ b/dom/base/FormData.cpp
@@ -18,42 +18,26 @@ using namespace mozilla::dom;
FormData::FormData(nsISupports* aOwner)
: nsFormSubmission(NS_LITERAL_CSTRING("UTF-8"), nullptr)
, mOwner(aOwner)
{
}
namespace {
-// Implements steps 3 and 4 of the "create an entry" algorithm of FormData.
-already_AddRefed<File>
-CreateNewFileInstance(Blob& aBlob, const Optional<nsAString>& aFilename,
- ErrorResult& aRv)
+already_AddRefed<Blob>
+GetBlobForFormDataStorage(Blob& aBlob, const Optional<nsAString>& aFilename,
+ ErrorResult& aRv)
{
- // Step 3 "If value is a Blob object and not a File object, set value to
- // a new File object, representing the same bytes, whose name attribute value
- // is "blob"."
- // Step 4 "If value is a File object and filename is given, set value to
- // a new File object, representing the same bytes, whose name attribute
- // value is filename."
- nsAutoString filename;
- if (aFilename.WasPassed()) {
- filename = aFilename.Value();
- } else {
- // If value is already a File and filename is not passed, the spec says not
- // to create a new instance.
- RefPtr<File> file = aBlob.ToFile();
- if (file) {
- return file.forget();
- }
-
- filename = NS_LITERAL_STRING("blob");
+ if (!aFilename.WasPassed()) {
+ RefPtr<Blob> blob = &aBlob;
+ return blob.forget();
}
- RefPtr<File> file = aBlob.ToFile(filename, aRv);
+ RefPtr<File> file = aBlob.ToFile(aFilename.Value(), aRv);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
return file.forget();
}
} // namespace
@@ -73,17 +57,17 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Fo
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(FormData)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOwner)
for (uint32_t i = 0, len = tmp->mFormData.Length(); i < len; ++i) {
ImplCycleCollectionTraverse(cb, tmp->mFormData[i].value,
- "mFormData[i].GetAsFile()", 0);
+ "mFormData[i].GetAsBlob()", 0);
}
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(FormData)
NS_IMPL_CYCLE_COLLECTING_ADDREF(FormData)
@@ -111,59 +95,59 @@ FormData::Append(const nsAString& aName,
ErrorResult& aRv)
{
AddNameValuePair(aName, aValue);
}
void
FormData::Append(const nsAString& aName, Blob& aBlob,
const Optional<nsAString>& aFilename,
- ErrorResult& aRv)
+ ErrorResult& aRv)
{
- RefPtr<File> file = CreateNewFileInstance(aBlob, aFilename, aRv);
+ RefPtr<Blob> blob = GetBlobForFormDataStorage(aBlob, aFilename, aRv);
if (NS_WARN_IF(aRv.Failed())) {
return;
}
- AddNameFilePair(aName, file);
+ AddNameBlobPair(aName, blob);
}
void
FormData::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
FormData::Get(const nsAString& aName,
- Nullable<OwningFileOrUSVString>& aOutValue)
+ Nullable<OwningBlobOrUSVString>& aOutValue)
{
for (uint32_t i = 0; i < mFormData.Length(); ++i) {
if (aName.Equals(mFormData[i].name)) {
aOutValue.SetValue() = mFormData[i].value;
return;
}
}
aOutValue.SetNull();
}
void
FormData::GetAll(const nsAString& aName,
- nsTArray<OwningFileOrUSVString>& aValues)
+ nsTArray<OwningBlobOrUSVString>& aValues)
{
for (uint32_t i = 0; i < mFormData.Length(); ++i) {
if (aName.Equals(mFormData[i].name)) {
- OwningFileOrUSVString* element = aValues.AppendElement();
+ OwningBlobOrUSVString* element = aValues.AppendElement();
*element = mFormData[i].value;
}
}
}
bool
FormData::Has(const nsAString& aName)
{
@@ -172,22 +156,22 @@ FormData::Has(const nsAString& aName)
return true;
}
}
return false;
}
nsresult
-FormData::AddNameFilePair(const nsAString& aName, File* aFile)
+FormData::AddNameBlobPair(const nsAString& aName, Blob* aBlob)
{
- MOZ_ASSERT(aFile);
+ MOZ_ASSERT(aBlob);
FormDataTuple* data = mFormData.AppendElement();
- SetNameFilePair(data, aName, aFile);
+ SetNameBlobPair(data, aName, aBlob);
return NS_OK;
}
FormData::FormDataTuple*
FormData::RemoveAllOthersAndGetFirstFormDataTuple(const nsAString& aName)
{
FormDataTuple* lastFoundTuple = nullptr;
uint32_t lastFoundIndex = mFormData.Length();
@@ -210,22 +194,22 @@ FormData::RemoveAllOthersAndGetFirstForm
void
FormData::Set(const nsAString& aName, Blob& aBlob,
const Optional<nsAString>& aFilename,
ErrorResult& aRv)
{
FormDataTuple* tuple = RemoveAllOthersAndGetFirstFormDataTuple(aName);
if (tuple) {
- RefPtr<File> file = CreateNewFileInstance(aBlob, aFilename, aRv);
+ RefPtr<Blob> blob = GetBlobForFormDataStorage(aBlob, aFilename, aRv);
if (NS_WARN_IF(aRv.Failed())) {
return;
}
- SetNameFilePair(tuple, aName, file);
+ SetNameBlobPair(tuple, aName, blob);
} else {
Append(aName, aBlob, aFilename, aRv);
}
}
void
FormData::Set(const nsAString& aName, const nsAString& aValue,
ErrorResult& aRv)
@@ -246,17 +230,17 @@ FormData::GetIterableLength() const
const nsAString&
FormData::GetKeyAtIndex(uint32_t aIndex) const
{
MOZ_ASSERT(aIndex < mFormData.Length());
return mFormData[aIndex].name;
}
-const OwningFileOrUSVString&
+const OwningBlobOrUSVString&
FormData::GetValueAtIndex(uint32_t aIndex) const
{
MOZ_ASSERT(aIndex < mFormData.Length());
return mFormData[aIndex].value;
}
void
FormData::SetNameValuePair(FormDataTuple* aData,
@@ -264,25 +248,25 @@ FormData::SetNameValuePair(FormDataTuple
const nsAString& aValue)
{
MOZ_ASSERT(aData);
aData->name = aName;
aData->value.SetAsUSVString() = aValue;
}
void
-FormData::SetNameFilePair(FormDataTuple* aData,
+FormData::SetNameBlobPair(FormDataTuple* aData,
const nsAString& aName,
- File* aFile)
+ Blob* aBlob)
{
MOZ_ASSERT(aData);
- MOZ_ASSERT(aFile);
+ MOZ_ASSERT(aBlob);
aData->name = aName;
- aData->value.SetAsFile() = aFile;
+ aData->value.SetAsBlob() = aBlob;
}
// -------------------------------------------------------------------------
// nsIDOMFormData
NS_IMETHODIMP
FormData::Append(const nsAString& aName, nsIVariant* aValue)
{
@@ -353,18 +337,31 @@ FormData::Constructor(const GlobalObject
NS_IMETHODIMP
FormData::GetSendInfo(nsIInputStream** aBody, uint64_t* aContentLength,
nsACString& aContentType, nsACString& aCharset)
{
nsFSMultipartFormData fs(NS_LITERAL_CSTRING("UTF-8"), nullptr);
for (uint32_t i = 0; i < mFormData.Length(); ++i) {
- if (mFormData[i].value.IsFile()) {
- fs.AddNameFilePair(mFormData[i].name, mFormData[i].value.GetAsFile());
+ if (mFormData[i].value.IsBlob()) {
+ RefPtr<File> file = mFormData[i].value.GetAsBlob()->ToFile();
+ if (file) {
+ fs.AddNameBlobPair(mFormData[i].name, file);
+ continue;
+ }
+
+ ErrorResult rv;
+ file =
+ mFormData[i].value.GetAsBlob()->ToFile(NS_LITERAL_STRING("blob"), rv);
+ if (NS_WARN_IF(rv.Failed())) {
+ return rv.StealNSResult();
+ }
+
+ fs.AddNameBlobPair(mFormData[i].name, file);
} else if (mFormData[i].value.IsUSVString()) {
fs.AddNameValuePair(mFormData[i].name,
mFormData[i].value.GetAsUSVString());
} else {
MOZ_CRASH("This should no be possible.");
}
}
--- a/dom/base/FormData.h
+++ b/dom/base/FormData.h
@@ -30,31 +30,31 @@ class FormData final : public nsIDOMForm
public nsWrapperCache
{
private:
~FormData() {}
struct FormDataTuple
{
nsString name;
- OwningFileOrUSVString value;
+ OwningBlobOrUSVString value;
};
// 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);
- void SetNameFilePair(FormDataTuple* aData,
+ void SetNameBlobPair(FormDataTuple* aData,
const nsAString& aName,
- File* aFile);
+ Blob* aBlob);
public:
explicit FormData(nsISupports* aOwner = nullptr);
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(FormData,
nsIDOMFormData)
@@ -79,51 +79,51 @@ public:
void Append(const nsAString& aName, const nsAString& aValue,
ErrorResult& aRv);
void Append(const nsAString& aName, Blob& aBlob,
const Optional<nsAString>& aFilename,
ErrorResult& aRv);
void Delete(const nsAString& aName);
- void Get(const nsAString& aName, Nullable<OwningFileOrUSVString>& aOutValue);
+ void Get(const nsAString& aName, Nullable<OwningBlobOrUSVString>& aOutValue);
- void GetAll(const nsAString& aName, nsTArray<OwningFileOrUSVString>& aValues);
+ void GetAll(const nsAString& aName, nsTArray<OwningBlobOrUSVString>& aValues);
bool Has(const nsAString& aName);
void Set(const nsAString& aName, Blob& aBlob,
const Optional<nsAString>& aFilename,
ErrorResult& aRv);
void Set(const nsAString& aName, const nsAString& aValue,
ErrorResult& aRv);
uint32_t GetIterableLength() const;
const nsAString& GetKeyAtIndex(uint32_t aIndex) const;
- const OwningFileOrUSVString& GetValueAtIndex(uint32_t aIndex) const;
+ const OwningBlobOrUSVString& GetValueAtIndex(uint32_t aIndex) const;
// nsFormSubmission
virtual nsresult
GetEncodedSubmission(nsIURI* aURI, nsIInputStream** aPostDataStream) override;
virtual nsresult AddNameValuePair(const nsAString& aName,
const nsAString& aValue) override
{
FormDataTuple* data = mFormData.AppendElement();
SetNameValuePair(data, aName, aValue);
return NS_OK;
}
- virtual nsresult AddNameFilePair(const nsAString& aName,
- File* aFile) override;
+ virtual nsresult AddNameBlobPair(const nsAString& aName,
+ Blob* aBlob) override;
typedef bool (*FormDataEntryCallback)(const nsString& aName,
- const OwningFileOrUSVString& aValue,
+ const OwningBlobOrUSVString& aValue,
void* aClosure);
uint32_t
Length() const
{
return mFormData.Length();
}
--- a/dom/base/StructuredCloneHolder.cpp
+++ b/dom/base/StructuredCloneHolder.cpp
@@ -831,24 +831,23 @@ ReadFormData(JSContext* aCx,
return nullptr;
}
if (tag == SCTAG_DOM_BLOB) {
MOZ_ASSERT(indexOrLengthOfString < aHolder->BlobImpls().Length());
RefPtr<BlobImpl> blobImpl =
aHolder->BlobImpls()[indexOrLengthOfString];
- MOZ_ASSERT(blobImpl->IsFile());
- RefPtr<File> file =
- File::Create(aHolder->ParentDuringRead(), blobImpl);
- MOZ_ASSERT(file);
+ RefPtr<Blob> blob =
+ Blob::Create(aHolder->ParentDuringRead(), blobImpl);
+ MOZ_ASSERT(blob);
ErrorResult rv;
- formData->Append(name, *file, thirdArg, rv);
+ formData->Append(name, *blob, thirdArg, rv);
if (NS_WARN_IF(rv.Failed())) {
return nullptr;
}
} else {
MOZ_ASSERT(tag == 0);
nsAutoString value;
@@ -907,26 +906,26 @@ WriteFormData(JSStructuredCloneWriter* a
public:
Closure(JSStructuredCloneWriter* aWriter,
StructuredCloneHolder* aHolder)
: mWriter(aWriter),
mHolder(aHolder)
{ }
static bool
- Write(const nsString& aName, const OwningFileOrUSVString& aValue,
+ Write(const nsString& aName, const OwningBlobOrUSVString& aValue,
void* aClosure)
{
Closure* closure = static_cast<Closure*>(aClosure);
if (!WriteString(closure->mWriter, aName)) {
return false;
}
- if (aValue.IsFile()) {
- BlobImpl* blobImpl = aValue.GetAsFile()->Impl();
+ if (aValue.IsBlob()) {
+ BlobImpl* blobImpl = aValue.GetAsBlob()->Impl();
if (!JS_WriteUint32Pair(closure->mWriter, SCTAG_DOM_BLOB,
closure->mHolder->BlobImpls().Length())) {
return false;
}
closure->mHolder->BlobImpls().AppendElement(blobImpl);
return true;
}
--- a/dom/base/test/test_bug1187157.html
+++ b/dom/base/test/test_bug1187157.html
@@ -11,19 +11,18 @@ https://bugzilla.mozilla.org/show_bug.cg
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=789315">Mozilla Bug 789315</a>
<form id="a"><input name="b" type="file"/></form>
<script type="text/javascript">
var obj = new FormData(document.getElementById('a')).get('b');
- ok(obj instanceof File, "This should return an empty File");
+ ok(obj instanceof Blob, "This should return an empty Blob");
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>
</body>
--- a/dom/html/HTMLInputElement.cpp
+++ b/dom/html/HTMLInputElement.cpp
@@ -5567,24 +5567,24 @@ HTMLInputElement::SubmitNamesValues(nsFo
// Submit file if its input type=file and this encoding method accepts files
//
if (mType == NS_FORM_INPUT_FILE) {
// Submit files
const nsTArray<RefPtr<File>>& files = GetFilesInternal();
for (uint32_t i = 0; i < files.Length(); ++i) {
- aFormSubmission->AddNameFilePair(name, files[i]);
+ aFormSubmission->AddNameBlobPair(name, files[i]);
}
if (files.IsEmpty()) {
RefPtr<BlobImpl> blobImpl =
- new BlobImplEmptyFile(NS_LITERAL_STRING("application/octet-stream"));
- RefPtr<File> file = File::Create(OwnerDoc()->GetInnerWindow(), blobImpl);
- aFormSubmission->AddNameFilePair(name, file);
+ new EmptyBlobImpl(NS_LITERAL_STRING("application/octet-stream"));
+ RefPtr<Blob> blob = Blob::Create(OwnerDoc()->GetInnerWindow(), blobImpl);
+ aFormSubmission->AddNameBlobPair(name, blob);
}
return NS_OK;
}
if (mType == NS_FORM_INPUT_HIDDEN && name.EqualsLiteral("_charset_")) {
nsCString charset;
aFormSubmission->GetCharset(charset);
--- a/dom/html/nsFormSubmission.cpp
+++ b/dom/html/nsFormSubmission.cpp
@@ -49,16 +49,27 @@ SendJSWarning(nsIDocument* aDocument,
{
nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
NS_LITERAL_CSTRING("HTML"), aDocument,
nsContentUtils::eFORMS_PROPERTIES,
aWarningName,
aWarningArgs, aWarningArgsLen);
}
+static void
+RetrieveFileName(Blob* aBlob, nsAString& aFilename)
+{
+ MOZ_ASSERT(aBlob);
+
+ RefPtr<File> file = aBlob->ToFile();
+ if (file) {
+ file->GetName(aFilename);
+ }
+}
+
// --------------------------------------------------------------------------
class nsFSURLEncoded : public nsEncodingFormSubmission
{
public:
/**
* @param aCharset the charset of the form as a string
* @param aMethod the method of the submit (either NS_FORM_METHOD_GET or
@@ -72,18 +83,18 @@ public:
mMethod(aMethod),
mDocument(aDocument),
mWarnedFileControl(false)
{
}
virtual nsresult AddNameValuePair(const nsAString& aName,
const nsAString& aValue) override;
- virtual nsresult AddNameFilePair(const nsAString& aName,
- File* aFile) override;
+ virtual nsresult AddNameBlobPair(const nsAString& aName,
+ Blob* aBlob) override;
virtual nsresult GetEncodedSubmission(nsIURI* aURI,
nsIInputStream** aPostDataStream)
override;
virtual bool SupportsIsindexSubmission() override
{
return true;
}
@@ -159,29 +170,28 @@ nsFSURLEncoded::AddIsindex(const nsAStri
} else {
mQueryString += NS_LITERAL_CSTRING("&isindex=") + convValue;
}
return NS_OK;
}
nsresult
-nsFSURLEncoded::AddNameFilePair(const nsAString& aName,
- File* aFile)
+nsFSURLEncoded::AddNameBlobPair(const nsAString& aName,
+ Blob* aBlob)
{
- MOZ_ASSERT(aFile);
+ MOZ_ASSERT(aBlob);
if (!mWarnedFileControl) {
SendJSWarning(mDocument, "ForgotFileEnctypeWarning", nullptr, 0);
mWarnedFileControl = true;
}
nsAutoString filename;
- aFile->GetName(filename);
-
+ RetrieveFileName(aBlob, filename);
return AddNameValuePair(aName, filename);
}
static void
HandleMailtoSubject(nsCString& aPath) {
// Walk through the string and see if we have a subject already.
bool hasSubject = false;
@@ -433,61 +443,64 @@ nsFSMultipartFormData::AddNameValuePair(
+ NS_LITERAL_CSTRING("Content-Disposition: form-data; name=\"")
+ nameStr + NS_LITERAL_CSTRING("\"" CRLF CRLF)
+ valueStr + NS_LITERAL_CSTRING(CRLF);
return NS_OK;
}
nsresult
-nsFSMultipartFormData::AddNameFilePair(const nsAString& aName,
- File* aFile)
+nsFSMultipartFormData::AddNameBlobPair(const nsAString& aName,
+ Blob* aBlob)
{
- MOZ_ASSERT(aFile);
+ MOZ_ASSERT(aBlob);
// Encode the control name
nsAutoCString nameStr;
nsresult rv = EncodeVal(aName, nameStr, true);
NS_ENSURE_SUCCESS(rv, rv);
nsAutoString filename16;
- aFile->GetName(filename16);
+ RetrieveFileName(aBlob, filename16);
ErrorResult error;
nsAutoString filepath16;
- aFile->GetPath(filepath16, error);
- if (NS_WARN_IF(error.Failed())) {
- return error.StealNSResult();
+ RefPtr<File> file = aBlob->ToFile();
+ if (file) {
+ file->GetPath(filepath16, error);
+ if (NS_WARN_IF(error.Failed())) {
+ return error.StealNSResult();
+ }
}
if (!filepath16.IsEmpty()) {
// File.path includes trailing "/"
filename16 = filepath16 + filename16;
}
nsAutoCString filename;
rv = EncodeVal(filename16, filename, true);
NS_ENSURE_SUCCESS(rv, rv);
// Get content type
nsAutoString contentType16;
- aFile->GetType(contentType16);
+ aBlob->GetType(contentType16);
if (contentType16.IsEmpty()) {
contentType16.AssignLiteral("application/octet-stream");
}
nsAutoCString contentType;
contentType.Adopt(nsLinebreakConverter::
ConvertLineBreaks(NS_ConvertUTF16toUTF8(contentType16).get(),
nsLinebreakConverter::eLinebreakAny,
nsLinebreakConverter::eLinebreakSpace));
// Get input stream
nsCOMPtr<nsIInputStream> fileStream;
- aFile->GetInternalStream(getter_AddRefs(fileStream), error);
+ aBlob->GetInternalStream(getter_AddRefs(fileStream), error);
if (NS_WARN_IF(error.Failed())) {
return error.StealNSResult();
}
if (fileStream) {
// Create buffered stream (for efficiency)
nsCOMPtr<nsIInputStream> bufferedStream;
rv = NS_NewBufferedInputStream(getter_AddRefs(bufferedStream),
@@ -512,17 +525,17 @@ nsFSMultipartFormData::AddNameFilePair(c
+ filename + NS_LITERAL_CSTRING("\"" CRLF)
+ NS_LITERAL_CSTRING("Content-Type: ")
+ contentType + NS_LITERAL_CSTRING(CRLF CRLF);
// We should not try to append an invalid stream. That will happen for example
// if we try to update a file that actually do not exist.
if (fileStream) {
ErrorResult error;
- uint64_t size = aFile->GetSize(error);
+ uint64_t size = aBlob->GetSize(error);
if (error.Failed()) {
error.SuppressException();
} else {
// We need to dump the data up to this point into the POST data stream
// here, since we're about to add the file input stream
AddPostDataStream();
mPostDataStream->AppendStream(fileStream);
@@ -585,18 +598,18 @@ class nsFSTextPlain : public nsEncodingF
public:
nsFSTextPlain(const nsACString& aCharset, nsIContent* aOriginatingElement)
: nsEncodingFormSubmission(aCharset, aOriginatingElement)
{
}
virtual nsresult AddNameValuePair(const nsAString& aName,
const nsAString& aValue) override;
- virtual nsresult AddNameFilePair(const nsAString& aName,
- File* aFile) override;
+ virtual nsresult AddNameBlobPair(const nsAString& aName,
+ Blob* aBlob) override;
virtual nsresult GetEncodedSubmission(nsIURI* aURI,
nsIInputStream** aPostDataStream)
override;
private:
nsString mBody;
};
@@ -609,22 +622,23 @@ nsFSTextPlain::AddNameValuePair(const ns
// values so we'll have to live with it.
mBody.Append(aName + NS_LITERAL_STRING("=") + aValue +
NS_LITERAL_STRING(CRLF));
return NS_OK;
}
nsresult
-nsFSTextPlain::AddNameFilePair(const nsAString& aName,
- File* aFile)
+nsFSTextPlain::AddNameBlobPair(const nsAString& aName,
+ Blob* aBlob)
{
+ MOZ_ASSERT(aBlob);
+
nsAutoString filename;
- aFile->GetName(filename);
-
+ RetrieveFileName(aBlob, filename);
AddNameValuePair(aName, filename);
return NS_OK;
}
nsresult
nsFSTextPlain::GetEncodedSubmission(nsIURI* aURI,
nsIInputStream** aPostDataStream)
{
--- a/dom/html/nsFormSubmission.h
+++ b/dom/html/nsFormSubmission.h
@@ -14,17 +14,17 @@
class nsIURI;
class nsIInputStream;
class nsGenericHTMLElement;
class nsIMultiplexInputStream;
namespace mozilla {
namespace dom {
-class File;
+class Blob;
} // namespace dom
} // namespace mozilla
/**
* Class for form submissions; encompasses the function to call to submit as
* well as the form submission name/value pairs
*/
class nsFormSubmission
@@ -40,23 +40,24 @@ public:
*
* @param aName the name of the parameter
* @param aValue the value of the parameter
*/
virtual nsresult AddNameValuePair(const nsAString& aName,
const nsAString& aValue) = 0;
/**
- * Submit a name/file pair
+ * Submit a name/blob pair
*
* @param aName the name of the parameter
- * @param aFile the file to submit. The file's name will be used
+ * @param aBlob the blob to submit. The file's name will be used if the Blob
+ * is actually a File, otherwise 'blob' string is used instead.
*/
- virtual nsresult AddNameFilePair(const nsAString& aName,
- mozilla::dom::File* aFile) = 0;
+ virtual nsresult AddNameBlobPair(const nsAString& aName,
+ mozilla::dom::Blob* aBlob) = 0;
/**
* Reports whether the instance supports AddIsindex().
*
* @return true if supported.
*/
virtual bool SupportsIsindexSubmission()
{
@@ -154,18 +155,18 @@ public:
* @param aCharset the charset of the form as a string
*/
nsFSMultipartFormData(const nsACString& aCharset,
nsIContent* aOriginatingElement);
~nsFSMultipartFormData();
virtual nsresult AddNameValuePair(const nsAString& aName,
const nsAString& aValue) override;
- virtual nsresult AddNameFilePair(const nsAString& aName,
- mozilla::dom::File* aFile) override;
+ virtual nsresult AddNameBlobPair(const nsAString& aName,
+ mozilla::dom::Blob* aBlob) override;
virtual nsresult GetEncodedSubmission(nsIURI* aURI,
nsIInputStream** aPostDataStream) override;
void GetContentType(nsACString& aContentType)
{
aContentType =
NS_LITERAL_CSTRING("multipart/form-data; boundary=") + mBoundary;
}
--- a/dom/html/test/formData_test.js
+++ b/dom/html/test/formData_test.js
@@ -76,17 +76,17 @@ function testSet() {
is(f.getAll("other").length, 1, "set() should replace existing entries.");
is(f.getAll("other")[0], "value4", "set() should replace existing entries.");
}
function testFilename() {
var f = new FormData();
// Spec says if a Blob (which is not a File) is added, the name parameter is set to "blob".
f.append("blob", new Blob(["hi"]));
- is(f.get("blob").name, "blob", "Blob's filename should be blob.");
+ ok(f.get("blob") instanceof Blob, "We should have a blob back.");
// If a filename is passed, that should replace the original.
f.append("blob2", new Blob(["hi"]), "blob2.txt");
is(f.get("blob2").name, "blob2.txt", "Explicit filename should override \"blob\".");
var file = new File(["hi"], "file1.txt");
f.append("file1", file);
// If a file is passed, the "create entry" algorithm should not create a new File, but reuse the existing one.
--- a/dom/html/test/test_formSubmission.html
+++ b/dom/html/test/test_formSubmission.html
@@ -585,17 +585,17 @@ var expectedAugment = [
{ name: "aNameNum", value: "9.2" },
{ name: "aNameFile1", value: placeholder_myFile1 },
{ name: "aNameFile2", value: placeholder_myFile2 },
//{ name: "aNameObj", value: "[object XMLHttpRequest]" },
//{ name: "aNameNull", value: "null" },
//{ name: "aNameUndef", value: "undefined" },
];
-function checkMPSubmission(sub, expected, test) {
+function checkMPSubmission(sub, expected, test, isFormData = false) {
function getPropCount(o) {
var x, l = 0;
for (x in o) ++l;
return l;
}
function mpquote(s) {
return s.replace(/\r\n/g, " ")
.replace(/\r/g, " ")
@@ -620,17 +620,17 @@ function checkMPSubmission(sub, expected
"Wrong number of headers in " + test);
is(sub[i].body,
expected[i].value.replace(/\r\n|\r|\n/, "\r\n"),
"Correct value in " + test);
}
else {
is(sub[i].headers["Content-Disposition"],
"form-data; name=\"" + mpquote(expected[i].name) + "\"; filename=\"" +
- mpquote(expected[i].fileName) + "\"",
+ mpquote(expected[i].fileName != "" || !isFormData ? expected[i].fileName : "blob") + "\"",
"Correct name in " + test);
is(sub[i].headers["Content-Type"],
expected[i].contentType,
"Correct content type in " + test);
is (getPropCount(sub[i].headers), 2,
"Wrong number of headers in " + test);
is(sub[i].body,
expected[i].value,
@@ -777,48 +777,48 @@ function runTest() {
checkURLSubmission(submission, expectedSub);
// Send form using XHR and FormData
xhr = new XMLHttpRequest();
xhr.onload = function() { gen.next(); };
xhr.open("POST", "form_submit_server.sjs");
xhr.send(new FormData(form));
yield undefined; // Wait for XHR load
- checkMPSubmission(JSON.parse(xhr.responseText), expectedSub, "send form using XHR and FormData");
+ checkMPSubmission(JSON.parse(xhr.responseText), expectedSub, "send form using XHR and FormData", true);
// Send disabled form using XHR and FormData
setDisabled(document.querySelectorAll("input, select, textarea"), true);
xhr.open("POST", "form_submit_server.sjs");
xhr.send(new FormData(form));
yield undefined;
- checkMPSubmission(JSON.parse(xhr.responseText), [], "send disabled form using XHR and FormData");
+ checkMPSubmission(JSON.parse(xhr.responseText), [], "send disabled form using XHR and FormData", true);
setDisabled(document.querySelectorAll("input, select, textarea"), false);
// Send FormData
function addToFormData(fd) {
fd.append("aName", "aValue");
fd.append("aNameNum", 9.2);
fd.append("aNameFile1", myFile1);
fd.append("aNameFile2", myFile2);
}
var fd = new FormData();
addToFormData(fd);
xhr.open("POST", "form_submit_server.sjs");
xhr.send(fd);
yield undefined;
- checkMPSubmission(JSON.parse(xhr.responseText), expectedAugment, "send FormData");
+ checkMPSubmission(JSON.parse(xhr.responseText), expectedAugment, "send FormData", true);
// Augment <form> using FormData
fd = new FormData(form);
addToFormData(fd);
xhr.open("POST", "form_submit_server.sjs");
xhr.send(fd);
yield undefined;
checkMPSubmission(JSON.parse(xhr.responseText),
- expectedSub.concat(expectedAugment), "send augmented FormData");
+ expectedSub.concat(expectedAugment), "send augmented FormData", true);
SimpleTest.finish();
yield undefined;
}
</script>
</pre>
</body>
--- a/dom/webidl/FormData.webidl
+++ b/dom/webidl/FormData.webidl
@@ -2,17 +2,17 @@
/* 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/.
*
* The origin of this IDL file is
* http://xhr.spec.whatwg.org
*/
-typedef (File or USVString) FormDataEntryValue;
+typedef (Blob or USVString) FormDataEntryValue;
[Constructor(optional HTMLFormElement form),
Exposed=(Window,Worker)]
interface FormData {
[Throws]
void append(USVString name, Blob value, optional USVString filename);
[Throws]
void append(USVString name, USVString value);