diff --git a/dom/fetch/Fetch.cpp b/dom/fetch/Fetch.cpp index 23e01ec813af..412e1d44bd9a 100644 --- a/dom/fetch/Fetch.cpp +++ b/dom/fetch/Fetch.cpp @@ -11,7 +11,6 @@ #include "nsIDocument.h" #include "nsIGlobalObject.h" #include "nsIStreamLoader.h" -#include "nsIThreadRetargetableRequest.h" #include "nsCharSeparatedTokenizer.h" #include "nsDOMString.h" diff --git a/dom/fetch/FetchConsumer.cpp b/dom/fetch/FetchConsumer.cpp index 0473d03d50f3..cde565705188 100644 --- a/dom/fetch/FetchConsumer.cpp +++ b/dom/fetch/FetchConsumer.cpp @@ -13,6 +13,7 @@ #include "mozilla/dom/WorkerScope.h" #include "mozilla/ipc/PBackgroundSharedTypes.h" #include "nsIInputStreamPump.h" +#include "nsIThreadRetargetableRequest.h" #include "nsProxyRelease.h" namespace mozilla { @@ -584,9 +585,7 @@ FetchBodyConsumer::BeginConsumeBodyMainThread() // Try to retarget, otherwise fall back to main thread. nsCOMPtr rr = do_QueryInterface(pump); - nsCOMPtr rl = - do_QueryInterface(listener); - if (rr && rl) { + if (rr) { nsCOMPtr sts = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID); rv = rr->RetargetDeliveryTo(sts); if (NS_FAILED(rv)) { diff --git a/dom/file/MutableBlobStorage.cpp b/dom/file/MutableBlobStorage.cpp index 78580e5db773..db6046f489de 100644 --- a/dom/file/MutableBlobStorage.cpp +++ b/dom/file/MutableBlobStorage.cpp @@ -108,7 +108,6 @@ public: CopyBuffer(MutableBlobStorage* aBlobStorage, const void* aData, uint32_t aLength) { - MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(aBlobStorage); MOZ_ASSERT(aData); @@ -162,7 +161,6 @@ private: , mData(aData) , mLength(aLength) { - MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(mBlobStorage); MOZ_ASSERT(aData); } @@ -335,7 +333,8 @@ private: MutableBlobStorage::MutableBlobStorage(MutableBlobStorageType aType, nsIEventTarget* aEventTarget, uint32_t aMaxMemory) - : mData(nullptr) + : mMutex("MutableBlobStorage::mMutex") + , mData(nullptr) , mDataLen(0) , mDataBufferLen(0) , mStorageState(aType == eOnlyInMemory ? eKeepInMemory : eInMemory) @@ -385,6 +384,8 @@ MutableBlobStorage::GetBlobWhenReady(nsISupports* aParent, MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(aCallback); + MutexAutoLock lock(mMutex); + // GetBlob can be called just once. MOZ_ASSERT(mStorageState != eClosed); StorageState previousState = mStorageState; @@ -449,7 +450,9 @@ MutableBlobStorage::GetBlobWhenReady(nsISupports* aParent, nsresult MutableBlobStorage::Append(const void* aData, uint32_t aLength) { - MOZ_ASSERT(NS_IsMainThread()); + // This method can be called on any thread. + + MutexAutoLock lock(mMutex); MOZ_ASSERT(mStorageState != eClosed); NS_ENSURE_ARG_POINTER(aData); @@ -459,8 +462,8 @@ MutableBlobStorage::Append(const void* aData, uint32_t aLength) // If eInMemory is the current Storage state, we could maybe migrate to // a temporary file. - if (mStorageState == eInMemory && ShouldBeTemporaryStorage(aLength) && - !MaybeCreateTemporaryFile()) { + if (mStorageState == eInMemory && ShouldBeTemporaryStorage(lock, aLength) && + !MaybeCreateTemporaryFile(lock)) { return NS_ERROR_FAILURE; } @@ -491,7 +494,7 @@ MutableBlobStorage::Append(const void* aData, uint32_t aLength) uint64_t offset = mDataLen; - if (!ExpandBufferSize(aLength)) { + if (!ExpandBufferSize(lock, aLength)) { return NS_ERROR_OUT_OF_MEMORY; } @@ -500,9 +503,9 @@ MutableBlobStorage::Append(const void* aData, uint32_t aLength) } bool -MutableBlobStorage::ExpandBufferSize(uint64_t aSize) +MutableBlobStorage::ExpandBufferSize(const MutexAutoLock& aProofOfLock, + uint64_t aSize) { - MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(mStorageState < eInTemporaryFile); if (mDataBufferLen >= mDataLen + aSize) { @@ -533,7 +536,8 @@ MutableBlobStorage::ExpandBufferSize(uint64_t aSize) } bool -MutableBlobStorage::ShouldBeTemporaryStorage(uint64_t aSize) const +MutableBlobStorage::ShouldBeTemporaryStorage(const MutexAutoLock& aProofOfLock, + uint64_t aSize) const { MOZ_ASSERT(mStorageState == eInMemory); @@ -548,16 +552,33 @@ MutableBlobStorage::ShouldBeTemporaryStorage(uint64_t aSize) const } bool -MutableBlobStorage::MaybeCreateTemporaryFile() +MutableBlobStorage::MaybeCreateTemporaryFile(const MutexAutoLock& aProofOfLock) +{ + mStorageState = eWaitingForTemporaryFile; + + if (!NS_IsMainThread()) { + RefPtr self = this; + nsCOMPtr r = NS_NewRunnableFunction( + "MutableBlobStorage::MaybeCreateTemporaryFile", + [self]() { self->MaybeCreateTemporaryFileOnMainThread(); }); + EventTarget()->Dispatch(r.forget(), NS_DISPATCH_SYNC); + return !!mActor; + } + + MaybeCreateTemporaryFileOnMainThread(); + return !!mActor; +} + +void +MutableBlobStorage::MaybeCreateTemporaryFileOnMainThread() { MOZ_ASSERT(NS_IsMainThread()); - - mStorageState = eWaitingForTemporaryFile; + MOZ_ASSERT(!mActor); mozilla::ipc::PBackgroundChild* actorChild = mozilla::ipc::BackgroundChild::GetOrCreateForCurrentThread(); if (NS_WARN_IF(!actorChild)) { - return false; + return; } mActor = new TemporaryIPCBlobChild(this); @@ -569,14 +590,14 @@ MutableBlobStorage::MaybeCreateTemporaryFile() mActor.get()->AddRef(); // The actor will call us when the FileDescriptor is received. - - return true; } void MutableBlobStorage::TemporaryFileCreated(PRFileDesc* aFD) { MOZ_ASSERT(NS_IsMainThread()); + + MutexAutoLock lock(mMutex); MOZ_ASSERT(mStorageState == eWaitingForTemporaryFile || mStorageState == eClosed); MOZ_ASSERT_IF(mPendingCallback, mStorageState == eClosed); @@ -643,6 +664,8 @@ MutableBlobStorage::AskForBlob(TemporaryIPCBlobChildCallback* aCallback, const nsACString& aContentType) { MOZ_ASSERT(NS_IsMainThread()); + + MutexAutoLock lock(mMutex); MOZ_ASSERT(mStorageState == eClosed); MOZ_ASSERT(mFD); MOZ_ASSERT(mActor); @@ -666,6 +689,8 @@ void MutableBlobStorage::ErrorPropagated(nsresult aRv) { MOZ_ASSERT(NS_IsMainThread()); + + MutexAutoLock lock(mMutex); mErrorResult = aRv; if (mActor) { @@ -695,16 +720,18 @@ MutableBlobStorage::DispatchToIOThread(already_AddRefed aRunnable) } size_t -MutableBlobStorage::SizeOfCurrentMemoryBuffer() const +MutableBlobStorage::SizeOfCurrentMemoryBuffer() { MOZ_ASSERT(NS_IsMainThread()); + MutexAutoLock lock(mMutex); return mStorageState < eInTemporaryFile ? mDataLen : 0; } PRFileDesc* -MutableBlobStorage::GetFD() const +MutableBlobStorage::GetFD() { MOZ_ASSERT(!NS_IsMainThread()); + MutexAutoLock lock(mMutex); return mFD; } @@ -712,6 +739,7 @@ void MutableBlobStorage::CloseFD() { MOZ_ASSERT(!NS_IsMainThread()); + MutexAutoLock lock(mMutex); MOZ_ASSERT(mFD); PR_Close(mFD); diff --git a/dom/file/MutableBlobStorage.h b/dom/file/MutableBlobStorage.h index 19b38ce25715..d2c7d25975b5 100644 --- a/dom/file/MutableBlobStorage.h +++ b/dom/file/MutableBlobStorage.h @@ -8,6 +8,7 @@ #define mozilla_dom_MutableBlobStorage_h #include "mozilla/RefPtr.h" +#include "mozilla/Mutex.h" #include "prio.h" class nsIEventTarget; @@ -35,7 +36,8 @@ public: nsresult aRv) = 0; }; -// This class is main-thread only. +// This class is must be created and used on main-thread, except for Append() +// that can be called on any thread. class MutableBlobStorage final { public: @@ -74,25 +76,31 @@ public: // Returns the heap size in bytes of our internal buffers. // Note that this intentionally ignores the data in the temp file. - size_t SizeOfCurrentMemoryBuffer() const; + size_t SizeOfCurrentMemoryBuffer(); - PRFileDesc* GetFD() const; + PRFileDesc* GetFD(); void CloseFD(); private: ~MutableBlobStorage(); - bool ExpandBufferSize(uint64_t aSize); + bool ExpandBufferSize(const MutexAutoLock& aProofOfLock, + uint64_t aSize); - bool ShouldBeTemporaryStorage(uint64_t aSize) const; + bool ShouldBeTemporaryStorage(const MutexAutoLock& aProofOfLock, + uint64_t aSize) const; - bool MaybeCreateTemporaryFile(); + bool MaybeCreateTemporaryFile(const MutexAutoLock& aProofOfLock); + void MaybeCreateTemporaryFileOnMainThread(); MOZ_MUST_USE nsresult DispatchToIOThread(already_AddRefed aRunnable); - // All these variables are touched on the main thread only. + Mutex mMutex; + + // All these variables are touched on the main thread only or in the + // retargeted thread when used by Append(). They are protected by mMutex. void* mData; uint64_t mDataLen; diff --git a/dom/file/MutableBlobStreamListener.cpp b/dom/file/MutableBlobStreamListener.cpp index b566a248c2ad..9487ded2d805 100644 --- a/dom/file/MutableBlobStreamListener.cpp +++ b/dom/file/MutableBlobStreamListener.cpp @@ -38,6 +38,7 @@ MutableBlobStreamListener::~MutableBlobStreamListener() NS_IMPL_ISUPPORTS(MutableBlobStreamListener, nsIStreamListener, + nsIThreadRetargetableStreamListener, nsIRequestObserver) NS_IMETHODIMP @@ -79,7 +80,7 @@ MutableBlobStreamListener::OnDataAvailable(nsIRequest* aRequest, uint64_t aSourceOffset, uint32_t aCount) { - MOZ_ASSERT(NS_IsMainThread()); + // This method could be called on any thread. MOZ_ASSERT(mStorage); uint32_t countRead; @@ -94,7 +95,7 @@ MutableBlobStreamListener::WriteSegmentFun(nsIInputStream* aWriterStream, uint32_t aCount, uint32_t* aWriteCount) { - MOZ_ASSERT(NS_IsMainThread()); + // This method could be called on any thread. MutableBlobStreamListener* self = static_cast(aClosure); MOZ_ASSERT(self->mStorage); @@ -108,5 +109,11 @@ MutableBlobStreamListener::WriteSegmentFun(nsIInputStream* aWriterStream, return NS_OK; } +NS_IMETHODIMP +MutableBlobStreamListener::CheckListenerChain() +{ + return NS_OK; +} + } // namespace net } // namespace mozilla diff --git a/dom/file/MutableBlobStreamListener.h b/dom/file/MutableBlobStreamListener.h index 47b36f044d8c..4ab7f32f7e53 100644 --- a/dom/file/MutableBlobStreamListener.h +++ b/dom/file/MutableBlobStreamListener.h @@ -8,6 +8,7 @@ #define mozilla_dom_MutableBlobStreamListener_h #include "nsIStreamListener.h" +#include "nsIThreadRetargetableStreamListener.h" #include "mozilla/dom/MutableBlobStorage.h" class nsIEventTarget; @@ -15,12 +16,13 @@ class nsIEventTarget; namespace mozilla { namespace dom { -// This class is main-thread only. class MutableBlobStreamListener final : public nsIStreamListener + , public nsIThreadRetargetableStreamListener { public: - NS_DECL_ISUPPORTS + NS_DECL_THREADSAFE_ISUPPORTS NS_DECL_NSISTREAMLISTENER + NS_DECL_NSITHREADRETARGETABLESTREAMLISTENER NS_DECL_NSIREQUESTOBSERVER MutableBlobStreamListener(MutableBlobStorage::MutableBlobStorageType aType,