diff --git a/dom/file/ipc/IPCBlobInputStream.cpp b/dom/file/ipc/IPCBlobInputStream.cpp index 71ac79cf09c7..ba0dfdeb74dd 100644 --- a/dom/file/ipc/IPCBlobInputStream.cpp +++ b/dom/file/ipc/IPCBlobInputStream.cpp @@ -192,6 +192,10 @@ IPCBlobInputStream::Clone(nsIInputStream** aResult) MOZ_ASSERT(mActor); nsCOMPtr stream = mActor->CreateStream(); + if (!stream) { + return NS_ERROR_FAILURE; + } + stream.forget(aResult); return NS_OK; } diff --git a/dom/file/ipc/IPCBlobInputStreamChild.cpp b/dom/file/ipc/IPCBlobInputStreamChild.cpp index fda381365bb3..6ad1948bade3 100644 --- a/dom/file/ipc/IPCBlobInputStreamChild.cpp +++ b/dom/file/ipc/IPCBlobInputStreamChild.cpp @@ -13,19 +13,17 @@ namespace { // This runnable is used in case the last stream is forgotten on the 'wrong' // thread. -class DeleteRunnable final : public Runnable +class ShutdownRunnable final : public Runnable { public: - explicit DeleteRunnable(IPCBlobInputStreamChild* aActor) + explicit ShutdownRunnable(IPCBlobInputStreamChild* aActor) : mActor(aActor) {} NS_IMETHOD Run() override { - if (mActor->IsAlive()) { - mActor->Send__delete__(mActor); - } + mActor->Shutdown(); return NS_OK; } @@ -96,10 +94,29 @@ IPCBlobInputStreamChild::~IPCBlobInputStreamChild() {} void -IPCBlobInputStreamChild::ActorDestroy(IProtocol::ActorDestroyReason aReason) +IPCBlobInputStreamChild::Shutdown() { MutexAutoLock lock(mMutex); - mActorAlive = false; + + RefPtr kungFuDeathGrip = this; + + mPendingOperations.Clear(); + + if (mActorAlive) { + SendClose(); + mActorAlive = false; + } +} + +void +IPCBlobInputStreamChild::ActorDestroy(IProtocol::ActorDestroyReason aReason) +{ + { + MutexAutoLock lock(mMutex); + mActorAlive = false; + } + + Shutdown(); } bool @@ -114,6 +131,10 @@ IPCBlobInputStreamChild::CreateStream() { MutexAutoLock lock(mMutex); + if (!mActorAlive) { + return nullptr; + } + RefPtr stream = new IPCBlobInputStream(this); mStreams.AppendElement(stream); return stream.forget(); @@ -124,7 +145,7 @@ IPCBlobInputStreamChild::ForgetStream(IPCBlobInputStream* aStream) { MOZ_ASSERT(aStream); - RefPtr kungFoDeathGrip = this; + RefPtr kungFuDeathGrip = this; { MutexAutoLock lock(mMutex); @@ -136,11 +157,11 @@ IPCBlobInputStreamChild::ForgetStream(IPCBlobInputStream* aStream) } if (mOwningThread == NS_GetCurrentThread()) { - Send__delete__(this); + Shutdown(); return; } - RefPtr runnable = new DeleteRunnable(this); + RefPtr runnable = new ShutdownRunnable(this); mOwningThread->Dispatch(runnable, NS_DISPATCH_NORMAL); } @@ -149,6 +170,11 @@ IPCBlobInputStreamChild::StreamNeeded(IPCBlobInputStream* aStream, nsIEventTarget* aEventTarget) { MutexAutoLock lock(mMutex); + + if (!mActorAlive) { + return; + } + MOZ_ASSERT(mStreams.Contains(aStream)); PendingOperation* opt = mPendingOperations.AppendElement(); @@ -175,6 +201,7 @@ IPCBlobInputStreamChild::RecvStreamReady(const OptionalIPCStream& aStream) { MutexAutoLock lock(mMutex); MOZ_ASSERT(!mPendingOperations.IsEmpty()); + MOZ_ASSERT(mActorAlive); pendingStream = mPendingOperations[0].mStream; eventTarget = mPendingOperations[0].mEventTarget; diff --git a/dom/file/ipc/IPCBlobInputStreamChild.h b/dom/file/ipc/IPCBlobInputStreamChild.h index 56fc77a28eff..403654bfd6be 100644 --- a/dom/file/ipc/IPCBlobInputStreamChild.h +++ b/dom/file/ipc/IPCBlobInputStreamChild.h @@ -56,6 +56,9 @@ public: mozilla::ipc::IPCResult RecvStreamReady(const OptionalIPCStream& aStream) override; + void + Shutdown(); + private: ~IPCBlobInputStreamChild(); diff --git a/dom/file/ipc/IPCBlobInputStreamParent.cpp b/dom/file/ipc/IPCBlobInputStreamParent.cpp index 5415d0259b1e..99f609cba92f 100644 --- a/dom/file/ipc/IPCBlobInputStreamParent.cpp +++ b/dom/file/ipc/IPCBlobInputStreamParent.cpp @@ -96,5 +96,17 @@ IPCBlobInputStreamParent::RecvStreamNeeded() return IPC_OK(); } +mozilla::ipc::IPCResult +IPCBlobInputStreamParent::RecvClose() +{ + MOZ_ASSERT(mContentManager || mPBackgroundManager); + + if (!Send__delete__(this)) { + return IPC_FAIL(this, "Send__delete_ failed"); + } + + return IPC_OK(); +} + } // namespace dom } // namespace mozilla diff --git a/dom/file/ipc/IPCBlobInputStreamParent.h b/dom/file/ipc/IPCBlobInputStreamParent.h index f1cd9dbc75a6..3ab06aed7013 100644 --- a/dom/file/ipc/IPCBlobInputStreamParent.h +++ b/dom/file/ipc/IPCBlobInputStreamParent.h @@ -44,6 +44,9 @@ public: mozilla::ipc::IPCResult RecvStreamNeeded() override; + mozilla::ipc::IPCResult + RecvClose() override; + private: IPCBlobInputStreamParent(const nsID& aID, uint64_t aSize, nsIContentParent* aManager); diff --git a/dom/file/ipc/PIPCBlobInputStream.ipdl b/dom/file/ipc/PIPCBlobInputStream.ipdl index 7fa48f2f6e81..35ec2345771a 100644 --- a/dom/file/ipc/PIPCBlobInputStream.ipdl +++ b/dom/file/ipc/PIPCBlobInputStream.ipdl @@ -20,11 +20,11 @@ protocol PIPCBlobInputStream parent: async StreamNeeded(); - - async __delete__(); + async Close(); child: async StreamReady(OptionalIPCStream aStream); + async __delete__(); }; } // namespace dom