Bug 1437640 - Implement nsIThreadRetargetableStreamListener in MutableBlobStreamListener, r=smaug
This commit is contained in:
@@ -11,7 +11,6 @@
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIGlobalObject.h"
|
||||
#include "nsIStreamLoader.h"
|
||||
#include "nsIThreadRetargetableRequest.h"
|
||||
|
||||
#include "nsCharSeparatedTokenizer.h"
|
||||
#include "nsDOMString.h"
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user