Bug 1437640 - Implement nsIThreadRetargetableStreamListener in MutableBlobStreamListener, r=smaug

This commit is contained in:
Andrea Marchesini
2018-02-14 13:23:01 +01:00
parent 6f761d6f48
commit ac387512d8
6 changed files with 76 additions and 33 deletions

View File

@@ -11,7 +11,6 @@
#include "nsIDocument.h"
#include "nsIGlobalObject.h"
#include "nsIStreamLoader.h"
#include "nsIThreadRetargetableRequest.h"
#include "nsCharSeparatedTokenizer.h"
#include "nsDOMString.h"

View File

@@ -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<Derived>::BeginConsumeBodyMainThread()
// Try to retarget, otherwise fall back to main thread.
nsCOMPtr<nsIThreadRetargetableRequest> rr = do_QueryInterface(pump);
nsCOMPtr<nsIThreadRetargetableStreamListener> rl =
do_QueryInterface(listener);
if (rr && rl) {
if (rr) {
nsCOMPtr<nsIEventTarget> sts = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
rv = rr->RetargetDeliveryTo(sts);
if (NS_FAILED(rv)) {

View File

@@ -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<MutableBlobStorage> self = this;
nsCOMPtr<nsIRunnable> 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<nsIRunnable> 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);

View File

@@ -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<nsIRunnable> 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;

View File

@@ -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<MutableBlobStreamListener*>(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

View File

@@ -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,