From ed883ce3f41eb52060c4b7a37d008801077036af Mon Sep 17 00:00:00 2001 From: Brindusan Cristian Date: Tue, 7 Jan 2020 16:30:53 +0200 Subject: [PATCH] Backed out changeset 61101e3eebb3 (bug 1030481) for mochitest failures at test_file.xhtml. CLOSED TREE --- dom/base/StructuredCloneHolder.cpp | 8 +++++++ dom/file/BaseBlobImpl.cpp | 26 ++++++++++++++++++++ dom/file/BaseBlobImpl.h | 9 +++++++ dom/file/Blob.cpp | 9 ++++++- dom/file/Blob.h | 10 +++++--- dom/file/BlobImpl.h | 4 ++++ dom/file/EmptyBlobImpl.cpp | 5 ++++ dom/file/EmptyBlobImpl.h | 8 +++++-- dom/file/FileBlobImpl.cpp | 38 +++++++++--------------------- dom/file/FileBlobImpl.h | 13 ---------- dom/file/MemoryBlobImpl.h | 1 + dom/file/MultipartBlobImpl.cpp | 27 +++++++++++++++++++++ dom/file/MultipartBlobImpl.h | 2 ++ dom/file/StreamBlobImpl.cpp | 2 ++ dom/indexedDB/FileSnapshot.h | 8 +++++++ dom/url/URLWorker.cpp | 13 ++++++++++ dom/xhr/XMLHttpRequestWorker.cpp | 8 +++++++ xpcom/base/moz.build | 1 + xpcom/base/nsIMutable.idl | 22 +++++++++++++++++ xpcom/build/XPCOM.h | 1 + 20 files changed, 169 insertions(+), 46 deletions(-) create mode 100644 xpcom/base/nsIMutable.idl diff --git a/dom/base/StructuredCloneHolder.cpp b/dom/base/StructuredCloneHolder.cpp index 2240a1e5042e..5a213f1930c8 100644 --- a/dom/base/StructuredCloneHolder.cpp +++ b/dom/base/StructuredCloneHolder.cpp @@ -464,6 +464,8 @@ JSObject* ReadBlob(JSContext* aCx, uint32_t aIndex, // pointer while destructors are running. RefPtr blobImpl = aHolder->BlobImpls()[aIndex]; + MOZ_ALWAYS_SUCCEEDS(blobImpl->SetMutable(false)); + RefPtr blob = Blob::Create(aHolder->GlobalDuringRead(), blobImpl); if (NS_WARN_IF(!blob)) { return nullptr; @@ -490,6 +492,7 @@ bool WriteBlob(JSStructuredCloneWriter* aWriter, Blob* aBlob, } RefPtr blobImpl = aBlob->Impl(); + MOZ_ALWAYS_SUCCEEDS(blobImpl->SetMutable(false)); // We store the position of the blobImpl in the array as index. if (JS_WriteUint32Pair(aWriter, SCTAG_DOM_BLOB, @@ -601,6 +604,8 @@ JSObject* ReadFileList(JSContext* aCx, JSStructuredCloneReader* aReader, RefPtr blobImpl = aHolder->BlobImpls()[pos]; MOZ_ASSERT(blobImpl->IsFile()); + MOZ_ALWAYS_SUCCEEDS(blobImpl->SetMutable(false)); + RefPtr file = File::Create(aHolder->GlobalDuringRead(), blobImpl); if (NS_WARN_IF(!file)) { return nullptr; @@ -640,6 +645,7 @@ bool WriteFileList(JSStructuredCloneWriter* aWriter, FileList* aFileList, for (uint32_t i = 0; i < aFileList->Length(); ++i) { RefPtr blobImpl = aFileList->Item(i)->Impl(); + MOZ_ALWAYS_SUCCEEDS(blobImpl->SetMutable(false)); blobImpls.AppendElement(blobImpl); } @@ -680,6 +686,7 @@ JSObject* ReadFormData(JSContext* aCx, JSStructuredCloneReader* aReader, MOZ_ASSERT(indexOrLengthOfString < aHolder->BlobImpls().Length()); RefPtr blobImpl = aHolder->BlobImpls()[indexOrLengthOfString]; + MOZ_ALWAYS_SUCCEEDS(blobImpl->SetMutable(false)); RefPtr blob = Blob::Create(aHolder->GlobalDuringRead(), blobImpl); if (NS_WARN_IF(!blob)) { @@ -778,6 +785,7 @@ bool WriteFormData(JSStructuredCloneWriter* aWriter, FormData* aFormData, } RefPtr blobImpl = aValue.GetAsBlob()->Impl(); + MOZ_ALWAYS_SUCCEEDS(blobImpl->SetMutable(false)); closure->mHolder->BlobImpls().AppendElement(blobImpl); return true; diff --git a/dom/file/BaseBlobImpl.cpp b/dom/file/BaseBlobImpl.cpp index 87f4ed3162c8..40037f246279 100644 --- a/dom/file/BaseBlobImpl.cpp +++ b/dom/file/BaseBlobImpl.cpp @@ -98,6 +98,32 @@ nsresult BaseBlobImpl::GetSendInfo(nsIInputStream** aBody, return NS_OK; } +nsresult BaseBlobImpl::GetMutable(bool* aMutable) const { + *aMutable = !mImmutable; + return NS_OK; +} + +nsresult BaseBlobImpl::SetMutable(bool aMutable) { + nsresult rv = NS_OK; + + NS_ENSURE_ARG(!mImmutable || !aMutable); + + if (!mImmutable && !aMutable) { + // Force the content type and size to be cached + nsAutoString dummyString; + GetType(dummyString); + + ErrorResult error; + GetSize(error); + if (NS_WARN_IF(error.Failed())) { + return error.StealNSResult(); + } + } + + mImmutable = !aMutable; + return rv; +} + /* static */ uint64_t BaseBlobImpl::NextSerialNumber() { static Atomic nextSerialNumber; diff --git a/dom/file/BaseBlobImpl.h b/dom/file/BaseBlobImpl.h index a407c43b5e35..c5874a26a6e2 100644 --- a/dom/file/BaseBlobImpl.h +++ b/dom/file/BaseBlobImpl.h @@ -19,6 +19,7 @@ class BaseBlobImpl : public BlobImpl { int64_t aLastModifiedDate) : mBlobImplType(aBlobImplType), mIsFile(true), + mImmutable(false), mContentType(aContentType), mName(aName), mStart(0), @@ -33,6 +34,7 @@ class BaseBlobImpl : public BlobImpl { const nsAString& aContentType, uint64_t aLength) : mBlobImplType(aBlobImplType), mIsFile(true), + mImmutable(false), mContentType(aContentType), mName(aName), mStart(0), @@ -47,6 +49,7 @@ class BaseBlobImpl : public BlobImpl { uint64_t aLength) : mBlobImplType(aBlobImplType), mIsFile(false), + mImmutable(false), mContentType(aContentType), mStart(0), mLength(aLength), @@ -60,6 +63,7 @@ class BaseBlobImpl : public BlobImpl { uint64_t aStart, uint64_t aLength) : mBlobImplType(aBlobImplType), mIsFile(false), + mImmutable(false), mContentType(aContentType), mStart(aStart), mLength(aLength), @@ -122,6 +126,10 @@ class BaseBlobImpl : public BlobImpl { nsACString& aContentType, nsACString& aCharset) override; + virtual nsresult GetMutable(bool* aMutable) const override; + + virtual nsresult SetMutable(bool aMutable) override; + virtual void SetLazyData(const nsAString& aName, const nsAString& aContentType, uint64_t aLength, int64_t aLastModifiedDate) override { @@ -159,6 +167,7 @@ class BaseBlobImpl : public BlobImpl { const nsString mBlobImplType; bool mIsFile; + bool mImmutable; nsString mContentType; nsString mName; diff --git a/dom/file/Blob.cpp b/dom/file/Blob.cpp index 3fbc9a39c195..89390a9c114d 100644 --- a/dom/file/Blob.cpp +++ b/dom/file/Blob.cpp @@ -40,8 +40,9 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_END NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Blob) NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY - NS_INTERFACE_MAP_ENTRY(nsISupports) + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIMutable) NS_INTERFACE_MAP_ENTRY_CONCRETE(Blob) + NS_INTERFACE_MAP_ENTRY(nsIMutable) NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference) NS_INTERFACE_MAP_END @@ -205,6 +206,12 @@ nsresult Blob::GetSendInfo(nsIInputStream** aBody, uint64_t* aContentLength, return mImpl->GetSendInfo(aBody, aContentLength, aContentType, aCharset); } +NS_IMETHODIMP +Blob::GetMutable(bool* aMutable) { return mImpl->GetMutable(aMutable); } + +NS_IMETHODIMP +Blob::SetMutable(bool aMutable) { return mImpl->SetMutable(aMutable); } + JSObject* Blob::WrapObject(JSContext* aCx, JS::Handle aGivenProto) { return Blob_Binding::Wrap(aCx, this, aGivenProto); } diff --git a/dom/file/Blob.h b/dom/file/Blob.h index 9e81f34daf09..9350317ff5eb 100644 --- a/dom/file/Blob.h +++ b/dom/file/Blob.h @@ -14,6 +14,7 @@ #include "mozilla/dom/BodyConsumer.h" #include "nsCycleCollectionParticipant.h" #include "nsCOMPtr.h" +#include "nsIMutable.h" #include "nsWrapperCache.h" #include "nsWeakReference.h" @@ -35,11 +36,14 @@ class Promise; } \ } -class Blob : public nsSupportsWeakReference, +class Blob : public nsIMutable, + public nsSupportsWeakReference, public nsWrapperCache { public: + NS_DECL_NSIMUTABLE + NS_DECL_CYCLE_COLLECTING_ISUPPORTS_FINAL - NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(Blob) + NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(Blob, nsIMutable) NS_DECLARE_STATIC_IID_ACCESSOR(NS_DOM_BLOB_IID) typedef OwningArrayBufferViewOrArrayBufferOrBlobOrUSVString BlobPart; @@ -154,7 +158,7 @@ size_t BindingJSObjectMallocBytes(Blob* aBlob); } // namespace mozilla inline nsISupports* ToSupports(mozilla::dom::Blob* aBlob) { - return static_cast(aBlob); + return static_cast(aBlob); } #endif // mozilla_dom_Blob_h diff --git a/dom/file/BlobImpl.h b/dom/file/BlobImpl.h index a185713516ff..eaf225b1f6f1 100644 --- a/dom/file/BlobImpl.h +++ b/dom/file/BlobImpl.h @@ -89,6 +89,10 @@ class BlobImpl : public nsISupports { nsACString& aContentType, nsACString& aCharset) = 0; + virtual nsresult GetMutable(bool* aMutable) const = 0; + + virtual nsresult SetMutable(bool aMutable) = 0; + virtual void SetLazyData(const nsAString& aName, const nsAString& aContentType, uint64_t aLength, int64_t aLastModifiedDate) = 0; diff --git a/dom/file/EmptyBlobImpl.cpp b/dom/file/EmptyBlobImpl.cpp index 761868eebc41..a9b1a2b5323e 100644 --- a/dom/file/EmptyBlobImpl.cpp +++ b/dom/file/EmptyBlobImpl.cpp @@ -15,6 +15,11 @@ already_AddRefed EmptyBlobImpl::CreateSlice( ErrorResult& aRv) { MOZ_ASSERT(!aStart && !aLength); RefPtr impl = new EmptyBlobImpl(aContentType); + + DebugOnly isMutable; + MOZ_ASSERT(NS_SUCCEEDED(impl->GetMutable(&isMutable))); + MOZ_ASSERT(!isMutable); + return impl.forget(); } diff --git a/dom/file/EmptyBlobImpl.h b/dom/file/EmptyBlobImpl.h index 9d89a46d87ae..ba2a9e250d6f 100644 --- a/dom/file/EmptyBlobImpl.h +++ b/dom/file/EmptyBlobImpl.h @@ -18,12 +18,16 @@ class EmptyBlobImpl final : public BaseBlobImpl { explicit EmptyBlobImpl(const nsAString& aContentType) : BaseBlobImpl(NS_LITERAL_STRING("EmptyBlobImpl"), aContentType, - 0 /* aLength */) {} + 0 /* aLength */) { + mImmutable = true; + } EmptyBlobImpl(const nsAString& aName, const nsAString& aContentType, int64_t aLastModifiedDate) : BaseBlobImpl(NS_LITERAL_STRING("EmptyBlobImpl"), aName, aContentType, 0, - aLastModifiedDate) {} + aLastModifiedDate) { + mImmutable = true; + } virtual void CreateInputStream(nsIInputStream** aStream, ErrorResult& aRv) override; diff --git a/dom/file/FileBlobImpl.cpp b/dom/file/FileBlobImpl.cpp index e8db32804cc4..617359a32ce1 100644 --- a/dom/file/FileBlobImpl.cpp +++ b/dom/file/FileBlobImpl.cpp @@ -21,7 +21,6 @@ namespace dom { FileBlobImpl::FileBlobImpl(nsIFile* aFile) : BaseBlobImpl(NS_LITERAL_STRING("FileBlobImpl"), EmptyString(), EmptyString(), UINT64_MAX, INT64_MAX), - mMutex("FileBlobImpl::mMutex"), mFile(aFile), mFileId(-1), mWholeFile(true) { @@ -38,7 +37,6 @@ FileBlobImpl::FileBlobImpl(const nsAString& aName, nsIFile* aFile) : BaseBlobImpl(NS_LITERAL_STRING("FileBlobImpl"), aName, aContentType, aLength, UINT64_MAX), - mMutex("FileBlobImpl::mMutex"), mFile(aFile), mFileId(-1), mWholeFile(true) { @@ -52,7 +50,6 @@ FileBlobImpl::FileBlobImpl(const nsAString& aName, nsIFile* aFile, int64_t aLastModificationDate) : BaseBlobImpl(NS_LITERAL_STRING("FileBlobImpl"), aName, aContentType, aLength, aLastModificationDate), - mMutex("FileBlobImpl::mMutex"), mFile(aFile), mFileId(-1), mWholeFile(true) { @@ -65,7 +62,6 @@ FileBlobImpl::FileBlobImpl(nsIFile* aFile, const nsAString& aName, const nsAString& aContentType, const nsAString& aBlobImplType) : BaseBlobImpl(aBlobImplType, aName, aContentType, UINT64_MAX, INT64_MAX), - mMutex("FileBlobImpl::mMutex"), mFile(aFile), mFileId(-1), mWholeFile(true) { @@ -83,12 +79,12 @@ FileBlobImpl::FileBlobImpl(const FileBlobImpl* aOther, uint64_t aStart, uint64_t aLength, const nsAString& aContentType) : BaseBlobImpl(NS_LITERAL_STRING("FileBlobImpl"), aContentType, aOther->mStart + aStart, aLength), - mMutex("FileBlobImpl::mMutex"), mFile(aOther->mFile), mFileId(-1), mWholeFile(false) { MOZ_ASSERT(mFile, "must have file"); MOZ_ASSERT(XRE_IsParentProcess()); + mImmutable = aOther->mImmutable; mMozFullPath = aOther->mMozFullPath; } @@ -104,8 +100,6 @@ void FileBlobImpl::GetMozFullPathInternal(nsAString& aFilename, ErrorResult& aRv) { MOZ_ASSERT(mIsFile, "Should only be called on files"); - MutexAutoLock lock(mMutex); - if (!mMozFullPath.IsVoid()) { aFilename = mMozFullPath; return; @@ -120,8 +114,6 @@ void FileBlobImpl::GetMozFullPathInternal(nsAString& aFilename, } uint64_t FileBlobImpl::GetSize(ErrorResult& aRv) { - MutexAutoLock lock(mMutex); - if (BaseBlobImpl::IsSizeUnknown()) { MOZ_ASSERT(mWholeFile, "Should only use lazy size when using the whole file"); @@ -142,14 +134,14 @@ uint64_t FileBlobImpl::GetSize(ErrorResult& aRv) { return mLength; } -class FileBlobImpl::GetTypeRunnable final : public WorkerMainThreadRunnable { +namespace { + +class GetTypeRunnable final : public WorkerMainThreadRunnable { public: - GetTypeRunnable(WorkerPrivate* aWorkerPrivate, FileBlobImpl* aBlobImpl, - const MutexAutoLock& aProofOfLock) + GetTypeRunnable(WorkerPrivate* aWorkerPrivate, BlobImpl* aBlobImpl) : WorkerMainThreadRunnable(aWorkerPrivate, NS_LITERAL_CSTRING("FileBlobImpl :: GetType")), - mBlobImpl(aBlobImpl), - mProofOfLock(aProofOfLock) { + mBlobImpl(aBlobImpl) { MOZ_ASSERT(aBlobImpl); aWorkerPrivate->AssertIsOnWorkerThread(); } @@ -158,24 +150,19 @@ class FileBlobImpl::GetTypeRunnable final : public WorkerMainThreadRunnable { MOZ_ASSERT(NS_IsMainThread()); nsAutoString type; - mBlobImpl->GetTypeInternal(type, mProofOfLock); + mBlobImpl->GetType(type); return true; } private: ~GetTypeRunnable() = default; - RefPtr mBlobImpl; - const MutexAutoLock& mProofOfLock; + RefPtr mBlobImpl; }; -void FileBlobImpl::GetType(nsAString& aType) { - MutexAutoLock lock(mMutex); - GetTypeInternal(aType, lock); -} +} // anonymous namespace -void FileBlobImpl::GetTypeInternal(nsAString& aType, - const MutexAutoLock& aProofOfLock) { +void FileBlobImpl::GetType(nsAString& aType) { aType.Truncate(); if (mContentType.IsVoid()) { @@ -191,7 +178,7 @@ void FileBlobImpl::GetTypeInternal(nsAString& aType, } RefPtr runnable = - new GetTypeRunnable(workerPrivate, this, aProofOfLock); + new GetTypeRunnable(workerPrivate, this); ErrorResult rv; runnable->Dispatch(Canceling, rv); @@ -223,9 +210,6 @@ void FileBlobImpl::GetTypeInternal(nsAString& aType, int64_t FileBlobImpl::GetLastModified(ErrorResult& aRv) { MOZ_ASSERT(mIsFile, "Should only be called on files"); - - MutexAutoLock lock(mMutex); - if (BaseBlobImpl::IsDateUnknown()) { PRTime msecs; aRv = mFile->GetLastModifiedTime(&msecs); diff --git a/dom/file/FileBlobImpl.h b/dom/file/FileBlobImpl.h index 9a6c0bf4c904..921947eb58e6 100644 --- a/dom/file/FileBlobImpl.h +++ b/dom/file/FileBlobImpl.h @@ -8,7 +8,6 @@ #define mozilla_dom_FileBlobImpl_h #include "mozilla/dom/BaseBlobImpl.h" -#include "mozilla/Mutex.h" class nsIFile; @@ -73,18 +72,6 @@ class FileBlobImpl : public BaseBlobImpl { const nsAString& aContentType, ErrorResult& aRv) override; - class GetTypeRunnable; - void GetTypeInternal(nsAString& aType, const MutexAutoLock& aProofOfLock); - - // FileBlobImpl is the only BlobImpl with a few getter methods with lazy - // initialization. Because any BlobImpl must work thread-safe, we use a mutex. - // This is the list of the getter methods and the corresponding lazy members: - // - GetMozFullPathInternal - mMozFullPath - // - GetSize - mLength - // - GetType - mContentType - // - GetLastModified - mLastModificationDate - Mutex mMutex; - nsCOMPtr mFile; nsString mMozFullPath; int64_t mFileId; diff --git a/dom/file/MemoryBlobImpl.h b/dom/file/MemoryBlobImpl.h index 47ca56b2fa39..acf28a8973cb 100644 --- a/dom/file/MemoryBlobImpl.h +++ b/dom/file/MemoryBlobImpl.h @@ -147,6 +147,7 @@ class MemoryBlobImpl final : public BaseBlobImpl { aOther->mStart + aStart, aLength), mDataOwner(aOther->mDataOwner) { MOZ_ASSERT(mDataOwner && mDataOwner->mData, "must have data"); + mImmutable = aOther->mImmutable; } ~MemoryBlobImpl() {} diff --git a/dom/file/MultipartBlobImpl.cpp b/dom/file/MultipartBlobImpl.cpp index ebb8205b8e2b..e8d494c18b75 100644 --- a/dom/file/MultipartBlobImpl.cpp +++ b/dom/file/MultipartBlobImpl.cpp @@ -283,6 +283,33 @@ void MultipartBlobImpl::SetLengthAndModifiedDate(ErrorResult& aRv) { } } +nsresult MultipartBlobImpl::SetMutable(bool aMutable) { + nsresult rv; + + // This looks a little sketchy since BlobImpl objects are supposed to be + // threadsafe. However, we try to enforce that all BlobImpl objects must be + // set to immutable *before* being passed to another thread, so this should + // be safe. + if (!aMutable && !mImmutable && !mBlobImpls.IsEmpty()) { + for (uint32_t index = 0, count = mBlobImpls.Length(); index < count; + index++) { + rv = mBlobImpls[index]->SetMutable(aMutable); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + } + } + + rv = BaseBlobImpl::SetMutable(aMutable); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + MOZ_ASSERT_IF(!aMutable, mImmutable); + + return NS_OK; +} + bool MultipartBlobImpl::MayBeClonedToOtherThreads() const { for (uint32_t i = 0; i < mBlobImpls.Length(); ++i) { if (!mBlobImpls[i]->MayBeClonedToOtherThreads()) { diff --git a/dom/file/MultipartBlobImpl.h b/dom/file/MultipartBlobImpl.h index 704c685c7783..f32e5e680ba9 100644 --- a/dom/file/MultipartBlobImpl.h +++ b/dom/file/MultipartBlobImpl.h @@ -59,6 +59,8 @@ class MultipartBlobImpl final : public BaseBlobImpl { return mBlobImpls.Length() ? &mBlobImpls : nullptr; } + virtual nsresult SetMutable(bool aMutable) override; + void SetName(const nsAString& aName) { mName = aName; } virtual bool MayBeClonedToOtherThreads() const override; diff --git a/dom/file/StreamBlobImpl.cpp b/dom/file/StreamBlobImpl.cpp index 5921259a3963..e5c833a273df 100644 --- a/dom/file/StreamBlobImpl.cpp +++ b/dom/file/StreamBlobImpl.cpp @@ -51,6 +51,7 @@ StreamBlobImpl::StreamBlobImpl(already_AddRefed aInputStream, mInputStream(std::move(aInputStream)), mIsDirectory(false), mFileId(-1) { + mImmutable = true; } StreamBlobImpl::StreamBlobImpl(already_AddRefed aInputStream, @@ -63,6 +64,7 @@ StreamBlobImpl::StreamBlobImpl(already_AddRefed aInputStream, mInputStream(std::move(aInputStream)), mIsDirectory(false), mFileId(-1) { + mImmutable = true; } StreamBlobImpl::~StreamBlobImpl() { UnregisterWeakMemoryReporter(this); } diff --git a/dom/indexedDB/FileSnapshot.h b/dom/indexedDB/FileSnapshot.h index ed3a84142f56..52b1f24f14ec 100644 --- a/dom/indexedDB/FileSnapshot.h +++ b/dom/indexedDB/FileSnapshot.h @@ -123,6 +123,14 @@ class BlobImplSnapshot final : public BlobImpl, public PIBlobImplSnapshot { aCharset); } + virtual nsresult GetMutable(bool* aMutable) const override { + return mBlobImpl->GetMutable(aMutable); + } + + virtual nsresult SetMutable(bool aMutable) override { + return mBlobImpl->SetMutable(aMutable); + } + virtual void SetLazyData(const nsAString& aName, const nsAString& aContentType, uint64_t aLength, int64_t aLastModifiedDate) override { diff --git a/dom/url/URLWorker.cpp b/dom/url/URLWorker.cpp index a256f41102d6..d5d268ad86f9 100644 --- a/dom/url/URLWorker.cpp +++ b/dom/url/URLWorker.cpp @@ -29,6 +29,10 @@ class CreateURLRunnable : public WorkerMainThreadRunnable { mBlobImpl(aBlobImpl), mURL(aURL) { MOZ_ASSERT(aBlobImpl); + + DebugOnly isMutable; + MOZ_ASSERT(NS_SUCCEEDED(aBlobImpl->GetMutable(&isMutable))); + MOZ_ASSERT(!isMutable); } bool MainThreadRun() override { @@ -36,6 +40,10 @@ class CreateURLRunnable : public WorkerMainThreadRunnable { AssertIsOnMainThread(); + DebugOnly isMutable; + MOZ_ASSERT(NS_SUCCEEDED(mBlobImpl->GetMutable(&isMutable))); + MOZ_ASSERT(!isMutable); + nsCOMPtr principal = mWorkerPrivate->GetPrincipal(); nsAutoCString url; @@ -155,6 +163,11 @@ void URLWorker::CreateObjectURL(const GlobalObject& aGlobal, Blob& aBlob, RefPtr blobImpl = aBlob.Impl(); MOZ_ASSERT(blobImpl); + aRv = blobImpl->SetMutable(false); + if (NS_WARN_IF(aRv.Failed())) { + return; + } + RefPtr runnable = new CreateURLRunnable(workerPrivate, blobImpl, aResult); diff --git a/dom/xhr/XMLHttpRequestWorker.cpp b/dom/xhr/XMLHttpRequestWorker.cpp index 9c4415ffb667..cb86623d9410 100644 --- a/dom/xhr/XMLHttpRequestWorker.cpp +++ b/dom/xhr/XMLHttpRequestWorker.cpp @@ -1893,6 +1893,14 @@ void XMLHttpRequestWorker::Send( RefPtr blob = &aData.Value().GetAsBlob(); MOZ_ASSERT(blob); + RefPtr blobImpl = blob->Impl(); + MOZ_ASSERT(blobImpl); + + aRv = blobImpl->SetMutable(false); + if (NS_WARN_IF(aRv.Failed())) { + return; + } + JS::Rooted value(aCx); if (!GetOrCreateDOMReflector(aCx, blob, &value)) { aRv.Throw(NS_ERROR_FAILURE); diff --git a/xpcom/base/moz.build b/xpcom/base/moz.build index 813b518857a3..a4f3f9aea2e5 100644 --- a/xpcom/base/moz.build +++ b/xpcom/base/moz.build @@ -18,6 +18,7 @@ XPIDL_SOURCES += [ 'nsIMemoryInfoDumper.idl', 'nsIMemoryReporter.idl', 'nsIMessageLoop.idl', + 'nsIMutable.idl', 'nsISecurityConsoleMessage.idl', 'nsISupports.idl', 'nsIUUIDGenerator.idl', diff --git a/xpcom/base/nsIMutable.idl b/xpcom/base/nsIMutable.idl new file mode 100644 index 000000000000..c5c7baab0f4d --- /dev/null +++ b/xpcom/base/nsIMutable.idl @@ -0,0 +1,22 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* 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/. */ + +#include "nsISupports.idl" + +/** + * nsIMutable defines an interface to be implemented by objects which + * can be made immutable. + */ +[scriptable, uuid(321578d0-03c1-4d95-8821-021ac612d18d)] +interface nsIMutable : nsISupports +{ + /** + * Control whether or not this object can be modified. If the flag is + * false, no modification is allowed. Once the flag has been set to false, + * it cannot be reset back to true -- attempts to do so throw + * NS_ERROR_INVALID_ARG. + */ + attribute boolean mutable; +}; diff --git a/xpcom/build/XPCOM.h b/xpcom/build/XPCOM.h index e072a7b7fbbc..41d679c9787f 100644 --- a/xpcom/build/XPCOM.h +++ b/xpcom/build/XPCOM.h @@ -77,6 +77,7 @@ #include "nsIInputStream.h" #include "nsIInterfaceRequestor.h" #include "nsILineInputStream.h" +#include "nsIMutable.h" #include "nsIObserver.h" #include "nsIObserverService.h" #include "nsIOutputStream.h"