author | Andrea Marchesini <amarchesini@mozilla.com> |
Fri, 04 Dec 2015 21:15:46 +0000 | |
changeset 311734 | 7f38782313bef9d359f7fb37ef331132e521c97c |
parent 311733 | 1f0e79c35b56d895e1b2bc9bbeca2eddfe387583 |
child 311735 | d271b9e473fd94209c42d747d0fd03b21185790c |
push id | 1040 |
push user | raliiev@mozilla.com |
push date | Mon, 29 Feb 2016 17:11:22 +0000 |
treeherder | mozilla-release@8c3167321162 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | bz |
bugs | 1230509 |
milestone | 45.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/dom/base/BlobSet.h +++ b/dom/base/BlobSet.h @@ -27,17 +27,18 @@ public: nsresult AppendVoidPtr(const void* aData, uint32_t aLength); nsresult AppendString(const nsAString& aString, bool nativeEOL, JSContext* aCx); nsresult AppendBlobImpl(BlobImpl* aBlobImpl); nsresult AppendBlobImpls(const nsTArray<RefPtr<BlobImpl>>& aBlobImpls); nsTArray<RefPtr<BlobImpl>>& GetBlobImpls() { Flush(); return mBlobImpls; } already_AddRefed<Blob> GetBlobInternal(nsISupports* aParent, - const nsACString& aContentType); + const nsACString& aContentType, + ErrorResult& aRv); protected: bool ExpandBufferSize(uint64_t aSize) { using mozilla::CheckedUint32; if (mDataBufferLen >= mDataLen + aSize) { mDataLen += aSize;
--- a/dom/base/File.cpp +++ b/dom/base/File.cpp @@ -252,26 +252,29 @@ Blob::ToFile() } else { file = new File(mParent, mImpl); } return file.forget(); } already_AddRefed<File> -Blob::ToFile(const nsAString& aName) const +Blob::ToFile(const nsAString& aName, ErrorResult& aRv) const { nsAutoTArray<RefPtr<BlobImpl>, 1> blobImpls; blobImpls.AppendElement(mImpl); nsAutoString contentType; mImpl->GetType(contentType); RefPtr<MultipartBlobImpl> impl = - new MultipartBlobImpl(blobImpls, aName, contentType); + MultipartBlobImpl::Create(blobImpls, aName, contentType, aRv); + if (NS_WARN_IF(aRv.Failed())) { + return nullptr; + } RefPtr<File> file = new File(mParent, impl); return file.forget(); } already_AddRefed<Blob> Blob::CreateSlice(uint64_t aStart, uint64_t aLength, const nsAString& aContentType, @@ -342,17 +345,21 @@ Blob::WrapObject(JSContext* aCx, JS::Han return BlobBinding::Wrap(aCx, this, aGivenProto); } /* static */ already_AddRefed<Blob> Blob::Constructor(const GlobalObject& aGlobal, ErrorResult& aRv) { RefPtr<MultipartBlobImpl> impl = new MultipartBlobImpl(); - impl->InitializeBlob(); + impl->InitializeBlob(aRv); + if (NS_WARN_IF(aRv.Failed())) { + return nullptr; + } + MOZ_ASSERT(!impl->IsFile()); RefPtr<Blob> blob = Blob::Create(aGlobal.GetAsSupports(), impl); return blob.forget(); } /* static */ already_AddRefed<Blob> Blob::Constructor( @@ -846,17 +853,17 @@ BlobImplFile::GetMozFullPathInternal(nsA { NS_ASSERTION(mIsFile, "Should only be called on files"); aRv = mFile->GetPath(aFilename); } uint64_t BlobImplFile::GetSize(ErrorResult& aRv) { - if (IsSizeUnknown()) { + if (BlobImplBase::IsSizeUnknown()) { NS_ASSERTION(mWholeFile, "Should only use lazy size when using the whole file"); int64_t fileSize; aRv = mFile->GetFileSize(&fileSize); if (NS_WARN_IF(aRv.Failed())) { return 0; } @@ -897,17 +904,17 @@ BlobImplFile::GetType(nsAString& aType) aType = mContentType; } int64_t BlobImplFile::GetLastModified(ErrorResult& aRv) { NS_ASSERTION(mIsFile, "Should only be called on files"); - if (IsDateUnknown()) { + if (BlobImplBase::IsDateUnknown()) { PRTime msecs; aRv = mFile->GetLastModifiedTime(&msecs); if (NS_WARN_IF(aRv.Failed())) { return 0; } mLastModificationDate = msecs; } @@ -1116,21 +1123,29 @@ BlobImplTemporaryBlob::GetInternalStream new nsTemporaryFileInputStream(mFileDescOwner, mStartPos, mStartPos + mLength); stream.forget(aStream); } //////////////////////////////////////////////////////////////////////////// // BlobSet implementation already_AddRefed<Blob> -BlobSet::GetBlobInternal(nsISupports* aParent, const nsACString& aContentType) +BlobSet::GetBlobInternal(nsISupports* aParent, + const nsACString& aContentType, + ErrorResult& aRv) { - RefPtr<Blob> blob = Blob::Create(aParent, - new MultipartBlobImpl(GetBlobImpls(), - NS_ConvertASCIItoUTF16(aContentType))); + RefPtr<BlobImpl> blobImpl = + MultipartBlobImpl::Create(GetBlobImpls(), + NS_ConvertASCIItoUTF16(aContentType), + aRv); + if (NS_WARN_IF(aRv.Failed())) { + return nullptr; + } + + RefPtr<Blob> blob = Blob::Create(aParent, blobImpl); return blob.forget(); } nsresult BlobSet::AppendVoidPtr(const void* aData, uint32_t aLength) { NS_ENSURE_ARG_POINTER(aData);
--- a/dom/base/File.h +++ b/dom/base/File.h @@ -113,17 +113,18 @@ public: // otherwise it returns a new File object with the same BlobImpl. already_AddRefed<File> ToFile(); // XXXjwatt Consider having a ToDirectory() method. The need for a FileSystem // object complicates that though. // This method creates a new File object with the given name and the same // BlobImpl. - already_AddRefed<File> ToFile(const nsAString& aName) const; + already_AddRefed<File> ToFile(const nsAString& aName, + ErrorResult& aRv) const; already_AddRefed<Blob> CreateSlice(uint64_t aStart, uint64_t aLength, const nsAString& aContentType, ErrorResult& aRv); void GetInternalStream(nsIInputStream** aStream, ErrorResult& aRv); @@ -793,16 +794,20 @@ public: ErrorResult& aRv) const override; virtual void GetInternalStream(nsIInputStream** aInputStream, ErrorResult& aRv) override; void SetPath(const nsAString& aFullPath); virtual void LookupAndCacheIsDirectory() override; + // We always have size and date for this kind of blob. + virtual bool IsSizeUnknown() const override { return false; } + virtual bool IsDateUnknown() const override { return false; } + protected: virtual ~BlobImplFile() { if (mFile && mIsTemporary) { NS_WARNING("In temporary ~BlobImplFile"); // Ignore errors if any, not much we can do. Clean-up will be done by // https://mxr.mozilla.org/mozilla-central/source/xpcom/io/nsAnonymousTemporaryFile.cpp?rev=6c1c7e45c902#127 #ifdef DEBUG nsresult rv =
--- a/dom/base/MultipartBlobImpl.cpp +++ b/dom/base/MultipartBlobImpl.cpp @@ -20,16 +20,47 @@ #include "nsIXPConnect.h" #include <algorithm> using namespace mozilla; using namespace mozilla::dom; NS_IMPL_ISUPPORTS_INHERITED0(MultipartBlobImpl, BlobImpl) +/* static */ already_AddRefed<MultipartBlobImpl> +MultipartBlobImpl::Create(const nsTArray<RefPtr<BlobImpl>>& aBlobImpls, + const nsAString& aName, + const nsAString& aContentType, + ErrorResult& aRv) +{ + RefPtr<MultipartBlobImpl> blobImpl = + new MultipartBlobImpl(aBlobImpls, aName, aContentType); + blobImpl->SetLengthAndModifiedDate(aRv); + if (NS_WARN_IF(aRv.Failed())) { + return nullptr; + } + + return blobImpl.forget(); +} + +/* static */ already_AddRefed<MultipartBlobImpl> +MultipartBlobImpl::Create(const nsTArray<RefPtr<BlobImpl>>& aBlobImpls, + const nsAString& aContentType, + ErrorResult& aRv) +{ + RefPtr<MultipartBlobImpl> blobImpl = + new MultipartBlobImpl(aBlobImpls, aContentType); + blobImpl->SetLengthAndModifiedDate(aRv); + if (NS_WARN_IF(aRv.Failed())) { + return nullptr; + } + + return blobImpl.forget(); +} + void MultipartBlobImpl::GetInternalStream(nsIInputStream** aStream, ErrorResult& aRv) { *aStream = nullptr; nsCOMPtr<nsIMultiplexInputStream> stream = do_CreateInstance("@mozilla.org/io/multiplex-input-stream;1"); @@ -120,25 +151,29 @@ MultipartBlobImpl::CreateSlice(uint64_t blobImpls.AppendElement(lastBlobImpl); } else { blobImpls.AppendElement(blobImpl); } length -= std::min<uint64_t>(l, length); } // we can create our blob now - RefPtr<BlobImpl> impl = - new MultipartBlobImpl(blobImpls, aContentType); + RefPtr<BlobImpl> impl = Create(blobImpls, aContentType, aRv); + if (NS_WARN_IF(aRv.Failed())) { + return nullptr; + } + return impl.forget(); } void -MultipartBlobImpl::InitializeBlob() +MultipartBlobImpl::InitializeBlob(ErrorResult& aRv) { - SetLengthAndModifiedDate(); + SetLengthAndModifiedDate(aRv); + NS_WARN_IF(aRv.Failed()); } void MultipartBlobImpl::InitializeBlob( JSContext* aCx, const Sequence<OwningArrayBufferOrArrayBufferViewOrBlobOrString>& aData, const nsAString& aContentType, bool aNativeEOL, @@ -182,47 +217,51 @@ MultipartBlobImpl::InitializeBlob( else { MOZ_CRASH("Impossible blob data type."); } } mBlobImpls = blobSet.GetBlobImpls(); - SetLengthAndModifiedDate(); + SetLengthAndModifiedDate(aRv); + NS_WARN_IF(aRv.Failed()); } void -MultipartBlobImpl::SetLengthAndModifiedDate() +MultipartBlobImpl::SetLengthAndModifiedDate(ErrorResult& aRv) { MOZ_ASSERT(mLength == UINT64_MAX); MOZ_ASSERT(mLastModificationDate == INT64_MAX); uint64_t totalLength = 0; int64_t lastModified = 0; bool lastModifiedSet = false; for (uint32_t index = 0, count = mBlobImpls.Length(); index < count; index++) { RefPtr<BlobImpl>& blob = mBlobImpls[index]; #ifdef DEBUG MOZ_ASSERT(!blob->IsSizeUnknown()); MOZ_ASSERT(!blob->IsDateUnknown()); #endif - ErrorResult error; - uint64_t subBlobLength = blob->GetSize(error); - MOZ_ALWAYS_TRUE(!error.Failed()); + uint64_t subBlobLength = blob->GetSize(aRv); + if (NS_WARN_IF(aRv.Failed())) { + return; + } MOZ_ASSERT(UINT64_MAX - subBlobLength >= totalLength); totalLength += subBlobLength; if (blob->IsFile()) { - int64_t partLastModified = blob->GetLastModified(error); - MOZ_ALWAYS_TRUE(!error.Failed()); + int64_t partLastModified = blob->GetLastModified(aRv); + if (NS_WARN_IF(aRv.Failed())) { + return; + } if (lastModified < partLastModified) { lastModified = partLastModified; lastModifiedSet = true; } } } @@ -309,17 +348,18 @@ MultipartBlobImpl::InitializeChromeFile( aBlob.GetType(mContentType); } BlobSet blobSet; blobSet.AppendBlobImpl(aBlob.Impl()); mBlobImpls = blobSet.GetBlobImpls(); - SetLengthAndModifiedDate(); + SetLengthAndModifiedDate(aRv); + NS_WARN_IF(aRv.Failed()); } void MultipartBlobImpl::InitializeChromeFile(nsPIDOMWindow* aWindow, nsIFile* aFile, const ChromeFilePropertyBag& aBag, bool aIsFromNsIFile, ErrorResult& aRv) @@ -380,17 +420,18 @@ MultipartBlobImpl::InitializeChromeFile( if (mContentType.IsEmpty()) { blob->GetType(mContentType); } BlobSet blobSet; blobSet.AppendBlobImpl(static_cast<File*>(blob.get())->Impl()); mBlobImpls = blobSet.GetBlobImpls(); - SetLengthAndModifiedDate(); + SetLengthAndModifiedDate(aRv); + NS_WARN_IF(aRv.Failed()); } void MultipartBlobImpl::InitializeChromeFile(nsPIDOMWindow* aWindow, const nsAString& aData, const ChromeFilePropertyBag& aBag, ErrorResult& aRv) {
--- a/dom/base/MultipartBlobImpl.h +++ b/dom/base/MultipartBlobImpl.h @@ -20,51 +20,43 @@ using namespace mozilla; using namespace mozilla::dom; class MultipartBlobImpl final : public BlobImplBase { public: NS_DECL_ISUPPORTS_INHERITED // Create as a file - MultipartBlobImpl(const nsTArray<RefPtr<BlobImpl>>& aBlobImpls, - const nsAString& aName, - const nsAString& aContentType) - : BlobImplBase(aName, aContentType, UINT64_MAX), - mBlobImpls(aBlobImpls), - mIsFromNsIFile(false) - { - SetLengthAndModifiedDate(); - } + static already_AddRefed<MultipartBlobImpl> + Create(const nsTArray<RefPtr<BlobImpl>>& aBlobImpls, + const nsAString& aName, + const nsAString& aContentType, + ErrorResult& aRv); // Create as a blob - MultipartBlobImpl(const nsTArray<RefPtr<BlobImpl>>& aBlobImpls, - const nsAString& aContentType) - : BlobImplBase(aContentType, UINT64_MAX), - mBlobImpls(aBlobImpls), - mIsFromNsIFile(false) - { - SetLengthAndModifiedDate(); - } + static already_AddRefed<MultipartBlobImpl> + Create(const nsTArray<RefPtr<BlobImpl>>& aBlobImpls, + const nsAString& aContentType, + ErrorResult& aRv); // Create as a file to be later initialized explicit MultipartBlobImpl(const nsAString& aName) : BlobImplBase(aName, EmptyString(), UINT64_MAX), mIsFromNsIFile(false) { } // Create as a blob to be later initialized MultipartBlobImpl() : BlobImplBase(EmptyString(), UINT64_MAX), mIsFromNsIFile(false) { } - void InitializeBlob(); + void InitializeBlob(ErrorResult& aRv); void InitializeBlob( JSContext* aCx, const Sequence<OwningArrayBufferOrArrayBufferViewOrBlobOrString>& aData, const nsAString& aContentType, bool aNativeEOL, ErrorResult& aRv); @@ -115,17 +107,34 @@ public: void SetFromNsIFile(bool aValue) { mIsFromNsIFile = aValue; } virtual bool MayBeClonedToOtherThreads() const override; protected: + MultipartBlobImpl(const nsTArray<RefPtr<BlobImpl>>& aBlobImpls, + const nsAString& aName, + const nsAString& aContentType) + : BlobImplBase(aName, aContentType, UINT64_MAX), + mBlobImpls(aBlobImpls), + mIsFromNsIFile(false) + { + } + + MultipartBlobImpl(const nsTArray<RefPtr<BlobImpl>>& aBlobImpls, + const nsAString& aContentType) + : BlobImplBase(aContentType, UINT64_MAX), + mBlobImpls(aBlobImpls), + mIsFromNsIFile(false) + { + } + virtual ~MultipartBlobImpl() {} - void SetLengthAndModifiedDate(); + void SetLengthAndModifiedDate(ErrorResult& aRv); nsTArray<RefPtr<BlobImpl>> mBlobImpls; bool mIsFromNsIFile; }; #endif // mozilla_dom_MultipartBlobImpl_h
--- a/dom/base/StructuredCloneHolder.cpp +++ b/dom/base/StructuredCloneHolder.cpp @@ -550,17 +550,18 @@ StructuredCloneHolder::WriteFullySeriali return false; } namespace { // Recursive! already_AddRefed<BlobImpl> EnsureBlobForBackgroundManager(BlobImpl* aBlobImpl, - PBackgroundChild* aManager = nullptr) + PBackgroundChild* aManager, + ErrorResult& aRv) { MOZ_ASSERT(aBlobImpl); RefPtr<BlobImpl> blobImpl = aBlobImpl; if (!aManager) { aManager = BackgroundChild::GetForCurrentThread(); if (!aManager) { return blobImpl.forget(); @@ -599,35 +600,44 @@ EnsureBlobForBackgroundManager(BlobImpl* bool newBlobImplNeeded = false; for (uint32_t index = 0; index < subBlobCount; index++) { const RefPtr<BlobImpl>& subBlobImpl = subBlobImpls->ElementAt(index); MOZ_ASSERT(subBlobImpl); RefPtr<BlobImpl>& newSubBlobImpl = newSubBlobImpls[index]; - newSubBlobImpl = EnsureBlobForBackgroundManager(subBlobImpl, aManager); + newSubBlobImpl = EnsureBlobForBackgroundManager(subBlobImpl, aManager, aRv); + if (NS_WARN_IF(aRv.Failed())) { + return nullptr; + } + MOZ_ASSERT(newSubBlobImpl); if (subBlobImpl != newSubBlobImpl) { newBlobImplNeeded = true; } } if (newBlobImplNeeded) { nsString contentType; blobImpl->GetType(contentType); if (blobImpl->IsFile()) { nsString name; blobImpl->GetName(name); - blobImpl = new MultipartBlobImpl(newSubBlobImpls, name, contentType); + blobImpl = MultipartBlobImpl::Create(newSubBlobImpls, name, + contentType, aRv); } else { - blobImpl = new MultipartBlobImpl(newSubBlobImpls, contentType); + blobImpl = MultipartBlobImpl::Create(newSubBlobImpls, contentType, aRv); + } + + if (NS_WARN_IF(aRv.Failed())) { + return nullptr; } MOZ_ALWAYS_TRUE(NS_SUCCEEDED(blobImpl->SetMutable(false))); } return blobImpl.forget(); } @@ -635,17 +645,23 @@ JSObject* ReadBlob(JSContext* aCx, uint32_t aIndex, StructuredCloneHolder* aHolder) { MOZ_ASSERT(aHolder); MOZ_ASSERT(aIndex < aHolder->BlobImpls().Length()); RefPtr<BlobImpl> blobImpl = aHolder->BlobImpls()[aIndex]; - blobImpl = EnsureBlobForBackgroundManager(blobImpl); + ErrorResult rv; + blobImpl = EnsureBlobForBackgroundManager(blobImpl, nullptr, rv); + if (NS_WARN_IF(rv.Failed())) { + rv.SuppressException(); + return nullptr; + } + MOZ_ASSERT(blobImpl); // RefPtr<File> needs to go out of scope before toObjectOrNull() is // called because the static analysis thinks dereferencing XPCOM objects // can GC (because in some cases it can!), and a return statement with a // JSObject* type means that JSObject* is on the stack as a raw pointer // while destructors are running. JS::Rooted<JS::Value> val(aCx); @@ -663,17 +679,24 @@ bool WriteBlob(JSStructuredCloneWriter* aWriter, Blob* aBlob, StructuredCloneHolder* aHolder) { MOZ_ASSERT(aWriter); MOZ_ASSERT(aBlob); MOZ_ASSERT(aHolder); - RefPtr<BlobImpl> blobImpl = EnsureBlobForBackgroundManager(aBlob->Impl()); + ErrorResult rv; + RefPtr<BlobImpl> blobImpl = + EnsureBlobForBackgroundManager(aBlob->Impl(), nullptr, rv); + if (NS_WARN_IF(rv.Failed())) { + rv.SuppressException(); + return false; + } + MOZ_ASSERT(blobImpl); MOZ_ALWAYS_TRUE(NS_SUCCEEDED(blobImpl->SetMutable(false))); // We store the position of the blobImpl in the array as index. if (JS_WriteUint32Pair(aWriter, SCTAG_DOM_BLOB, aHolder->BlobImpls().Length())) { aHolder->BlobImpls().AppendElement(blobImpl); @@ -709,17 +732,23 @@ ReadFileList(JSContext* aCx, // |aCount| is the number of BlobImpls to use from the |offset|. for (uint32_t i = 0; i < aCount; ++i) { uint32_t index = offset + i; MOZ_ASSERT(index < aHolder->BlobImpls().Length()); RefPtr<BlobImpl> blobImpl = aHolder->BlobImpls()[index]; MOZ_ASSERT(blobImpl->IsFile()); - blobImpl = EnsureBlobForBackgroundManager(blobImpl); + ErrorResult rv; + blobImpl = EnsureBlobForBackgroundManager(blobImpl, nullptr, rv); + if (NS_WARN_IF(rv.Failed())) { + rv.SuppressException(); + return nullptr; + } + MOZ_ASSERT(blobImpl); RefPtr<File> file = File::Create(aHolder->ParentDuringRead(), blobImpl); if (!fileList->Append(file)) { return nullptr; } } @@ -748,24 +777,32 @@ WriteFileList(JSStructuredCloneWriter* a // starting from the offset. if (!JS_WriteUint32Pair(aWriter, SCTAG_DOM_FILELIST, aFileList->Length()) || !JS_WriteUint32Pair(aWriter, 0, aHolder->BlobImpls().Length())) { return false; } + ErrorResult rv; + nsTArray<RefPtr<BlobImpl>> blobImpls; + for (uint32_t i = 0; i < aFileList->Length(); ++i) { RefPtr<BlobImpl> blobImpl = - EnsureBlobForBackgroundManager(aFileList->Item(i)->Impl()); + EnsureBlobForBackgroundManager(aFileList->Item(i)->Impl(), nullptr, rv); + if (NS_WARN_IF(rv.Failed())) { + rv.SuppressException(); + return false; + } + MOZ_ASSERT(blobImpl); - - aHolder->BlobImpls().AppendElement(blobImpl); + blobImpls.AppendElement(blobImpl); } + aHolder->BlobImpls().AppendElements(blobImpls); return true; } // Read the WriteFormData for the format. JSObject* ReadFormData(JSContext* aCx, JSStructuredCloneReader* aReader, uint32_t aCount, @@ -799,29 +836,38 @@ ReadFormData(JSContext* aCx, RefPtr<BlobImpl> blobImpl = aHolder->BlobImpls()[indexOrLengthOfString]; MOZ_ASSERT(blobImpl->IsFile()); RefPtr<File> file = File::Create(aHolder->ParentDuringRead(), blobImpl); MOZ_ASSERT(file); - formData->Append(name, *file, thirdArg); + ErrorResult rv; + formData->Append(name, *file, thirdArg, rv); + if (NS_WARN_IF(rv.Failed())) { + return nullptr; + } + } else { MOZ_ASSERT(tag == 0); nsAutoString value; value.SetLength(indexOrLengthOfString); size_t charSize = sizeof(nsString::char_type); if (!JS_ReadBytes(aReader, (void*) value.BeginWriting(), indexOrLengthOfString * charSize)) { return nullptr; } - formData->Append(name, value); + ErrorResult rv; + formData->Append(name, value, rv); + if (NS_WARN_IF(rv.Failed())) { + return nullptr; + } } } if (!ToJSValue(aCx, formData, &val)) { return nullptr; } }
--- a/dom/base/nsFormData.cpp +++ b/dom/base/nsFormData.cpp @@ -20,17 +20,18 @@ nsFormData::nsFormData(nsISupports* aOwn , 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) +CreateNewFileInstance(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; @@ -42,17 +43,22 @@ CreateNewFileInstance(Blob& aBlob, const RefPtr<File> file = aBlob.ToFile(); if (file) { return file.forget(); } filename = NS_LITERAL_STRING("blob"); } - return aBlob.ToFile(filename); + RefPtr<File> file = aBlob.ToFile(filename, aRv); + if (NS_WARN_IF(aRv.Failed())) { + return nullptr; + } + + return file.forget(); } } // namespace // ------------------------------------------------------------------------- // nsISupports NS_IMPL_CYCLE_COLLECTION_CLASS(nsFormData) @@ -96,26 +102,32 @@ nsresult nsFormData::GetEncodedSubmission(nsIURI* aURI, nsIInputStream** aPostDataStream) { NS_NOTREACHED("Shouldn't call nsFormData::GetEncodedSubmission"); return NS_OK; } void -nsFormData::Append(const nsAString& aName, const nsAString& aValue) +nsFormData::Append(const nsAString& aName, const nsAString& aValue, + ErrorResult& aRv) { AddNameValuePair(aName, aValue); } void nsFormData::Append(const nsAString& aName, Blob& aBlob, - const Optional<nsAString>& aFilename) + const Optional<nsAString>& aFilename, + ErrorResult& aRv) { - RefPtr<File> file = CreateNewFileInstance(aBlob, aFilename); + RefPtr<File> file = CreateNewFileInstance(aBlob, aFilename, aRv); + if (NS_WARN_IF(aRv.Failed())) { + return; + } + AddNameFilePair(aName, file); } 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. @@ -191,35 +203,41 @@ nsFormData::RemoveAllOthersAndGetFirstFo } } return lastFoundTuple; } void nsFormData::Set(const nsAString& aName, Blob& aBlob, - const Optional<nsAString>& aFilename) + const Optional<nsAString>& aFilename, + ErrorResult& aRv) { FormDataTuple* tuple = RemoveAllOthersAndGetFirstFormDataTuple(aName); if (tuple) { - RefPtr<File> file = CreateNewFileInstance(aBlob, aFilename); + RefPtr<File> file = CreateNewFileInstance(aBlob, aFilename, aRv); + if (NS_WARN_IF(aRv.Failed())) { + return; + } + SetNameFilePair(tuple, aName, file); } else { - Append(aName, aBlob, aFilename); + Append(aName, aBlob, aFilename, aRv); } } void -nsFormData::Set(const nsAString& aName, const nsAString& aValue) +nsFormData::Set(const nsAString& aName, const nsAString& aValue, + ErrorResult& aRv) { FormDataTuple* tuple = RemoveAllOthersAndGetFirstFormDataTuple(aName); if (tuple) { SetNameValuePair(tuple, aName, aValue); } else { - Append(aName, aValue); + Append(aName, aValue, aRv); } } uint32_t nsFormData::GetIterableLength() const { return mFormData.Length(); } @@ -256,30 +274,40 @@ nsFormData::Append(const nsAString& aNam NS_ENSURE_SUCCESS(rv, rv); free(iid); nsCOMPtr<nsIDOMBlob> domBlob = do_QueryInterface(supports); RefPtr<Blob> blob = static_cast<Blob*>(domBlob.get()); if (domBlob) { Optional<nsAString> temp; - Append(aName, *blob, temp); + ErrorResult rv; + Append(aName, *blob, temp, rv); + if (NS_WARN_IF(rv.Failed())) { + return rv.StealNSResult(); + } + return NS_OK; } } char16_t* stringData = nullptr; uint32_t stringLen = 0; rv = aValue->GetAsWStringWithSize(&stringLen, &stringData); NS_ENSURE_SUCCESS(rv, rv); nsString valAsString; valAsString.Adopt(stringData, stringLen); - Append(aName, valAsString); + ErrorResult error; + Append(aName, valAsString, error); + if (NS_WARN_IF(error.Failed())) { + return error.StealNSResult(); + } + return NS_OK; } /* virtual */ JSObject* nsFormData::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) { return FormDataBinding::Wrap(aCx, this, aGivenProto); }
--- a/dom/base/nsFormData.h +++ b/dom/base/nsFormData.h @@ -88,26 +88,30 @@ public: 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, const nsAString& aValue, + mozilla::ErrorResult& aRv); void Append(const nsAString& aName, Blob& aBlob, - const mozilla::dom::Optional<nsAString>& aFilename); + const mozilla::dom::Optional<nsAString>& aFilename, + mozilla::ErrorResult& aRv); void Delete(const nsAString& aName); void Get(const nsAString& aName, mozilla::dom::Nullable<OwningFileOrUSVString>& aOutValue); void GetAll(const nsAString& aName, nsTArray<OwningFileOrUSVString>& aValues); bool Has(const nsAString& aName); void Set(const nsAString& aName, Blob& aBlob, - const mozilla::dom::Optional<nsAString>& aFilename); - void Set(const nsAString& aName, const nsAString& aValue); + const mozilla::dom::Optional<nsAString>& aFilename, + mozilla::ErrorResult& aRv); + void Set(const nsAString& aName, const nsAString& aValue, + mozilla::ErrorResult& aRv); uint32_t GetIterableLength() const; const nsAString& GetKeyAtIndex(uint32_t aIndex) const; const OwningFileOrUSVString& GetValueAtIndex(uint32_t aIndex) const; // nsFormSubmission virtual nsresult GetEncodedSubmission(nsIURI* aURI, nsIInputStream** aPostDataStream) override;
--- a/dom/base/nsXMLHttpRequest.cpp +++ b/dom/base/nsXMLHttpRequest.cpp @@ -793,43 +793,42 @@ nsXMLHttpRequest::CreateResponseParsedJS return NS_ERROR_FAILURE; } mResultJSON = value; return NS_OK; } void -nsXMLHttpRequest::CreatePartialBlob() +nsXMLHttpRequest::CreatePartialBlob(ErrorResult& aRv) { if (mDOMBlob) { // Use progress info to determine whether load is complete, but use // mDataAvailable to ensure a slice is created based on the uncompressed // data count. if (mLoadTotal == mLoadTransferred) { mResponseBlob = mDOMBlob; } else { - ErrorResult rv; mResponseBlob = mDOMBlob->CreateSlice(0, mDataAvailable, - EmptyString(), rv); + EmptyString(), aRv); } return; } // mBlobSet can be null if the request has been canceled if (!mBlobSet) { return; } nsAutoCString contentType; if (mLoadTotal == mLoadTransferred) { mChannel->GetContentType(contentType); } - mResponseBlob = mBlobSet->GetBlobInternal(GetOwner(), contentType); + mResponseBlob = mBlobSet->GetBlobInternal(GetOwner(), contentType, aRv); } NS_IMETHODIMP nsXMLHttpRequest::GetResponseType(nsAString& aResponseType) { switch (mResponseType) { case XML_HTTP_RESPONSE_TYPE_DEFAULT: aResponseType.Truncate(); break; @@ -1013,17 +1012,17 @@ nsXMLHttpRequest::GetResponse(JSContext* { if (!(mState & XML_HTTP_REQUEST_DONE)) { if (mResponseType != XML_HTTP_RESPONSE_TYPE_MOZ_BLOB) { aResponse.setNull(); return; } if (!mResponseBlob) { - CreatePartialBlob(); + CreatePartialBlob(aRv); } } if (!mResponseBlob) { aResponse.setNull(); return; } @@ -2206,18 +2205,24 @@ nsXMLHttpRequest::OnStopRequest(nsIReque // and if the response length is zero. if (!mBlobSet) { mBlobSet = new BlobSet(); } // Smaller files may be written in cache map instead of separate files. // Also, no-store response cannot be written in persistent cache. nsAutoCString contentType; mChannel->GetContentType(contentType); - mResponseBlob = mBlobSet->GetBlobInternal(GetOwner(), contentType); + + ErrorResult rv; + mResponseBlob = mBlobSet->GetBlobInternal(GetOwner(), contentType, rv); mBlobSet = nullptr; + + if (NS_WARN_IF(rv.Failed())) { + return rv.StealNSResult(); + } } NS_ASSERTION(mResponseBody.IsEmpty(), "mResponseBody should be empty"); NS_ASSERTION(mResponseText.IsEmpty(), "mResponseText should be empty"); } else if (NS_SUCCEEDED(status) && ((mResponseType == XML_HTTP_RESPONSE_TYPE_ARRAYBUFFER && !mIsMappedArrayBuffer) || mResponseType == XML_HTTP_RESPONSE_TYPE_CHUNKED_ARRAYBUFFER)) { // set the capacity down to the actual length, to realloc back
--- a/dom/base/nsXMLHttpRequest.h +++ b/dom/base/nsXMLHttpRequest.h @@ -600,17 +600,17 @@ protected: nsresult AppendToResponseText(const char * aBuffer, uint32_t aBufferLen); static NS_METHOD StreamReaderFunc(nsIInputStream* in, void* closure, const char* fromRawSegment, uint32_t toOffset, uint32_t count, uint32_t *writeCount); nsresult CreateResponseParsedJSON(JSContext* aCx); - void CreatePartialBlob(); + void CreatePartialBlob(ErrorResult& aRv); bool CreateDOMBlob(nsIRequest *request); // Change the state of the object with this. The broadcast argument // determines if the onreadystatechange listener should be called. nsresult ChangeState(uint32_t aState, bool aBroadcast = true); already_AddRefed<nsILoadGroup> GetLoadGroup() const; nsIURI *GetBaseURI(); already_AddRefed<nsIHttpChannel> GetCurrentHttpChannel();
--- a/dom/fetch/FetchUtil.cpp +++ b/dom/fetch/FetchUtil.cpp @@ -198,17 +198,19 @@ public: : mFormData(aFormData) { MOZ_ASSERT(aFormData); } bool URLParamsIterator(const nsString& aName, const nsString& aValue) override { - mFormData->Append(aName, aValue); + ErrorResult rv; + mFormData->Append(aName, aValue, rv); + MOZ_ASSERT(!rv.Failed()); return true; } private: nsFormData* mFormData; }; /** @@ -387,17 +389,19 @@ private: if (!mFormData) { mFormData = new nsFormData(); } NS_ConvertUTF8toUTF16 name(mName); if (mFilename.IsVoid()) { - mFormData->Append(name, NS_ConvertUTF8toUTF16(body)); + ErrorResult rv; + mFormData->Append(name, NS_ConvertUTF8toUTF16(body), rv); + MOZ_ASSERT(!rv.Failed()); } else { // Unfortunately we've to copy the data first since all our strings are // going to free it. We also need fallible alloc, so we can't just use // ToNewCString(). char* copy = static_cast<char*>(moz_xmalloc(body.Length())); if (!copy) { NS_WARNING("Failed to copy File entry body."); return false; @@ -412,17 +416,21 @@ private: p = nullptr; RefPtr<Blob> file = File::CreateMemoryFile(mParentObject, reinterpret_cast<void *>(copy), body.Length(), NS_ConvertUTF8toUTF16(mFilename), NS_ConvertUTF8toUTF16(mContentType), /* aLastModifiedDate */ 0); Optional<nsAString> dummy; - mFormData->Append(name, *file, dummy); + ErrorResult rv; + mFormData->Append(name, *file, dummy, rv); + if (NS_WARN_IF(rv.Failed())) { + return false; + } } return true; } public: FormDataParser(const nsACString& aMimeType, const nsACString& aData, nsIGlobalObject* aParent) : mMimeType(aMimeType), mData(aData), mState(START_PART), mParentObject(aParent)
--- a/dom/ipc/Blob.cpp +++ b/dom/ipc/Blob.cpp @@ -899,23 +899,27 @@ CreateBlobImpl(const nsTArray<BlobData>& return nullptr; } DebugOnly<bool> isMutable; MOZ_ASSERT(NS_SUCCEEDED(blobImpl->GetMutable(&isMutable))); MOZ_ASSERT(!isMutable); } + ErrorResult rv; RefPtr<BlobImpl> blobImpl; if (!hasRecursed && aMetadata.IsFile()) { - blobImpl = - new MultipartBlobImpl(blobImpls, aMetadata.mName, aMetadata.mContentType); + blobImpl = MultipartBlobImpl::Create(blobImpls, aMetadata.mName, + aMetadata.mContentType, rv); } else { - blobImpl = - new MultipartBlobImpl(blobImpls, aMetadata.mContentType); + blobImpl = MultipartBlobImpl::Create(blobImpls, aMetadata.mContentType, rv); + } + + if (NS_WARN_IF(rv.Failed())) { + return nullptr; } MOZ_ALWAYS_TRUE(NS_SUCCEEDED(blobImpl->SetMutable(false))); return blobImpl.forget(); } already_AddRefed<BlobImpl>
--- a/dom/webidl/FormData.webidl +++ b/dom/webidl/FormData.webidl @@ -7,18 +7,22 @@ * http://xhr.spec.whatwg.org */ typedef (File 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); void delete(USVString name); FormDataEntryValue? get(USVString name); sequence<FormDataEntryValue> getAll(USVString name); boolean has(USVString name); + [Throws] void set(USVString name, Blob value, optional USVString filename); + [Throws] void set(USVString name, USVString value); iterable<USVString, FormDataEntryValue>; };