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