Bug 1359718 - Get rid of PBlob - part 1 - Remove PBlobStream, r=smaug, r=kanru

This commit is contained in:
Andrea Marchesini 2017-05-23 18:04:27 +02:00
parent 28479706ea
commit bc8f9a2827
7 changed files with 2 additions and 894 deletions

View File

@ -22,8 +22,6 @@
#include "mozilla/dom/BaseBlobImpl.h"
#include "mozilla/dom/nsIContentParent.h"
#include "mozilla/dom/nsIContentChild.h"
#include "mozilla/dom/PBlobStreamChild.h"
#include "mozilla/dom/PBlobStreamParent.h"
#include "mozilla/dom/indexedDB/FileSnapshot.h"
#include "mozilla/dom/IndexedDatabaseManager.h"
#include "mozilla/ipc/InputStreamUtils.h"
@ -562,32 +560,6 @@ private:
namespace {
class InputStreamChild final
: public PBlobStreamChild
{
RefPtr<RemoteInputStream> mRemoteStream;
public:
explicit
InputStreamChild(RemoteInputStream* aRemoteStream)
: mRemoteStream(aRemoteStream)
{
MOZ_ASSERT(aRemoteStream);
aRemoteStream->AssertIsOnOwningThread();
}
InputStreamChild()
{ }
~InputStreamChild() override = default;
private:
// This method is only called by the IPDL message machinery.
mozilla::ipc::IPCResult
Recv__delete__(const InputStreamParams& aParams,
const OptionalFileDescriptorSet& aFDs) override;
};
struct MOZ_STACK_CLASS CreateBlobImplMetadata final
{
nsString mContentType;
@ -1018,7 +990,7 @@ RemoteInputStream::BlockAndWaitForStream()
InputStreamParams params;
OptionalFileDescriptorSet optionalFDs;
mActor->SendBlobStreamSync(mStart, mLength, &params, &optionalFDs);
// This method is broken now...
nsTArray<FileDescriptor> fds;
OptionalFileDescriptorSetToFDs(optionalFDs, fds);
@ -1376,88 +1348,6 @@ RemoteInputStream::BlockAndGetInternalStream()
return mStream;
}
class InputStreamParent final
: public PBlobStreamParent
{
typedef mozilla::ipc::InputStreamParams InputStreamParams;
typedef mozilla::dom::OptionalFileDescriptorSet OptionalFileDescriptorSet;
bool* mSyncLoopGuard;
InputStreamParams* mParams;
OptionalFileDescriptorSet* mFDs;
NS_DECL_OWNINGTHREAD
public:
InputStreamParent()
: mSyncLoopGuard(nullptr)
, mParams(nullptr)
, mFDs(nullptr)
{
AssertIsOnOwningThread();
MOZ_COUNT_CTOR(InputStreamParent);
}
InputStreamParent(bool* aSyncLoopGuard,
InputStreamParams* aParams,
OptionalFileDescriptorSet* aFDs)
: mSyncLoopGuard(aSyncLoopGuard)
, mParams(aParams)
, mFDs(aFDs)
{
AssertIsOnOwningThread();
MOZ_ASSERT(aSyncLoopGuard);
MOZ_ASSERT(!*aSyncLoopGuard);
MOZ_ASSERT(aParams);
MOZ_ASSERT(aFDs);
MOZ_COUNT_CTOR(InputStreamParent);
}
~InputStreamParent() override
{
AssertIsOnOwningThread();
MOZ_COUNT_DTOR(InputStreamParent);
}
void
AssertIsOnOwningThread() const
{
NS_ASSERT_OWNINGTHREAD(InputStreamParent);
}
bool
Destroy(const InputStreamParams& aParams,
const OptionalFileDescriptorSet& aFDs)
{
AssertIsOnOwningThread();
if (mSyncLoopGuard) {
MOZ_ASSERT(!*mSyncLoopGuard);
*mSyncLoopGuard = true;
*mParams = aParams;
*mFDs = aFDs;
// We're not a live actor so manage the memory ourselves.
delete this;
return true;
}
// This will be destroyed by BlobParent::DeallocPBlobStreamParent.
return PBlobStreamParent::Send__delete__(this, aParams, aFDs);
}
private:
// This method is only called by the IPDL message machinery.
void
ActorDestroy(ActorDestroyReason aWhy) override
{
// Nothing needs to be done here.
}
};
StaticAutoPtr<BlobParent::IDTable> BlobParent::sIDTable;
StaticAutoPtr<Mutex> BlobParent::sIDTableMutex;
@ -1561,244 +1451,6 @@ private:
bool aIgnoreProcessID);
};
/*******************************************************************************
* BlobParent::OpenStreamRunnable Declaration
******************************************************************************/
// Each instance of this class will be dispatched to the network stream thread
// pool to run the first time where it will open the file input stream. It will
// then dispatch itself back to the owning thread to send the child process its
// response (assuming that the child has not crashed). The runnable will then
// dispatch itself to the thread pool again in order to close the file input
// stream.
class BlobParent::OpenStreamRunnable final
: public Runnable
{
friend class nsRevocableEventPtr<OpenStreamRunnable>;
// Only safe to access these pointers if mRevoked is false!
BlobParent* mBlobActor;
InputStreamParent* mStreamActor;
nsCOMPtr<nsIInputStream> mStream;
nsCOMPtr<nsIIPCSerializableInputStream> mSerializable;
nsCOMPtr<nsIEventTarget> mActorTarget;
nsCOMPtr<nsIThread> mIOTarget;
bool mRevoked;
bool mClosing;
public:
OpenStreamRunnable(BlobParent* aBlobActor,
InputStreamParent* aStreamActor,
nsIInputStream* aStream,
nsIIPCSerializableInputStream* aSerializable,
nsIThread* aIOTarget)
: mBlobActor(aBlobActor)
, mStreamActor(aStreamActor)
, mStream(aStream)
, mSerializable(aSerializable)
, mIOTarget(aIOTarget)
, mRevoked(false)
, mClosing(false)
{
MOZ_ASSERT(aBlobActor);
aBlobActor->AssertIsOnOwningThread();
MOZ_ASSERT(aStreamActor);
MOZ_ASSERT(aStream);
// aSerializable may be null.
MOZ_ASSERT(aIOTarget);
if (!NS_IsMainThread()) {
AssertIsOnBackgroundThread();
mActorTarget = do_GetCurrentThread();
MOZ_ASSERT(mActorTarget);
}
AssertIsOnOwningThread();
}
nsresult
Dispatch()
{
AssertIsOnOwningThread();
MOZ_ASSERT(mIOTarget);
nsresult rv = mIOTarget->Dispatch(this, NS_DISPATCH_NORMAL);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
NS_DECL_ISUPPORTS_INHERITED
private:
~OpenStreamRunnable() override = default;
bool
IsOnOwningThread() const
{
return EventTargetIsOnCurrentThread(mActorTarget);
}
void
AssertIsOnOwningThread() const
{
MOZ_ASSERT(IsOnOwningThread());
}
void
Revoke()
{
AssertIsOnOwningThread();
#ifdef DEBUG
mBlobActor = nullptr;
mStreamActor = nullptr;
#endif
mRevoked = true;
}
nsresult
OpenStream()
{
MOZ_ASSERT(!IsOnOwningThread());
MOZ_ASSERT(mStream);
if (!mSerializable) {
nsCOMPtr<IPrivateRemoteInputStream> remoteStream =
do_QueryInterface(mStream);
MOZ_ASSERT(remoteStream, "Must QI to IPrivateRemoteInputStream here!");
nsCOMPtr<nsIInputStream> realStream =
remoteStream->BlockAndGetInternalStream();
NS_ENSURE_TRUE(realStream, NS_ERROR_FAILURE);
mSerializable = do_QueryInterface(realStream);
if (!mSerializable) {
MOZ_ASSERT(false, "Must be serializable!");
return NS_ERROR_FAILURE;
}
mStream.swap(realStream);
}
// To force the stream open we call Available(). We don't actually care
// how much data is available.
uint64_t available;
if (NS_FAILED(mStream->Available(&available))) {
NS_WARNING("Available failed on this stream!");
}
if (mActorTarget) {
nsresult rv = mActorTarget->Dispatch(this, NS_DISPATCH_NORMAL);
NS_ENSURE_SUCCESS(rv, rv);
} else {
MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(this));
}
return NS_OK;
}
nsresult
CloseStream()
{
MOZ_ASSERT(!IsOnOwningThread());
MOZ_ASSERT(mStream);
// Going to always release here.
nsCOMPtr<nsIInputStream> stream;
mStream.swap(stream);
nsCOMPtr<nsIThread> ioTarget;
mIOTarget.swap(ioTarget);
DebugOnly<nsresult> rv = stream->Close();
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Failed to close stream!");
MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(NewRunnableMethod(ioTarget, &nsIThread::Shutdown)));
return NS_OK;
}
nsresult
SendResponse()
{
AssertIsOnOwningThread();
MOZ_ASSERT(mStream);
MOZ_ASSERT(mSerializable);
MOZ_ASSERT(mIOTarget);
MOZ_ASSERT(!mClosing);
nsCOMPtr<nsIIPCSerializableInputStream> serializable;
mSerializable.swap(serializable);
if (mRevoked) {
MOZ_ASSERT(!mBlobActor);
MOZ_ASSERT(!mStreamActor);
}
else {
MOZ_ASSERT(mBlobActor);
MOZ_ASSERT(mBlobActor->HasManager());
MOZ_ASSERT(mStreamActor);
InputStreamParams params;
nsTArray<FileDescriptor> fds;
serializable->Serialize(params, fds);
MOZ_ASSERT(params.type() != InputStreamParams::T__None);
OptionalFileDescriptorSet optionalFDSet;
if (nsIContentParent* contentManager = mBlobActor->GetContentManager()) {
ConstructFileDescriptorSet(contentManager, fds, optionalFDSet);
} else {
ConstructFileDescriptorSet(mBlobActor->GetBackgroundManager(),
fds,
optionalFDSet);
}
mStreamActor->Destroy(params, optionalFDSet);
mBlobActor->NoteRunnableCompleted(this);
#ifdef DEBUG
mBlobActor = nullptr;
mStreamActor = nullptr;
#endif
}
// If our luck is *really* bad then it is possible for the CloseStream() and
// nsIThread::Shutdown() functions to run before the Dispatch() call here
// finishes... Keep the thread alive until this method returns.
nsCOMPtr<nsIThread> kungFuDeathGrip = mIOTarget;
mClosing = true;
nsresult rv = kungFuDeathGrip->Dispatch(this, NS_DISPATCH_NORMAL);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
NS_IMETHOD
Run() override
{
MOZ_ASSERT(mIOTarget);
if (IsOnOwningThread()) {
return SendResponse();
}
if (!mClosing) {
return OpenStream();
}
return CloseStream();
}
};
NS_IMPL_ISUPPORTS_INHERITED0(BlobParent::OpenStreamRunnable, Runnable)
/*******************************************************************************
* BlobChild::RemoteBlobImpl Declaration
******************************************************************************/
@ -1808,7 +1460,6 @@ class BlobChild::RemoteBlobImpl
, public nsIRemoteBlob
{
protected:
class CreateStreamHelper;
class WorkerHolder;
BlobChild* mActor;
@ -1939,13 +1590,6 @@ public:
mDifferentProcessBlobImpl = nullptr;
}
// Used only by CreateStreamHelper, it dispatches a runnable to the target
// thread. This thread can be the main-thread, the background thread or a
// worker. If the thread is a worker, the aRunnable is wrapper into a
// ControlRunnable in order to avoid to be blocked into a sync event loop.
nsresult
DispatchToTarget(nsIRunnable* aRunnable);
void
WorkerHasNotified();
@ -1986,36 +1630,6 @@ public:
}
};
class BlobChild::RemoteBlobImpl::CreateStreamHelper final
: public CancelableRunnable
{
Monitor mMonitor;
RefPtr<RemoteBlobImpl> mRemoteBlobImpl;
RefPtr<RemoteInputStream> mInputStream;
const uint64_t mStart;
const uint64_t mLength;
bool mDone;
public:
explicit CreateStreamHelper(RemoteBlobImpl* aRemoteBlobImpl);
nsresult
GetStream(nsIInputStream** aInputStream);
NS_IMETHOD Run() override;
private:
~CreateStreamHelper() override
{
MOZ_ASSERT(!mRemoteBlobImpl);
MOZ_ASSERT(!mInputStream);
MOZ_ASSERT(mDone);
}
void
RunInternal(RemoteBlobImpl* aBaseRemoteBlobImpl, bool aNotify);
};
class BlobChild::RemoteBlobSliceImpl final
: public RemoteBlobImpl
{
@ -2439,11 +2053,7 @@ RemoteBlobImpl::GetInternalStream(nsIInputStream** aStream, ErrorResult& aRv)
return;
}
RefPtr<CreateStreamHelper> helper = new CreateStreamHelper(this);
aRv = helper->GetStream(aStream);
if (NS_WARN_IF(aRv.Failed())) {
return;
}
// Broken method...
}
int64_t
@ -2541,38 +2151,6 @@ public:
}
};
nsresult
BlobChild::
RemoteBlobImpl::DispatchToTarget(nsIRunnable* aRunnable)
{
MOZ_ASSERT(aRunnable);
// We have to protected mWorkerPrivate because this method can be called by
// any thread (sort of).
MutexAutoLock lock(mMutex);
if (mWorkerPrivate) {
MOZ_ASSERT(mWorkerHolder);
RefPtr<RemoteBlobControlRunnable> controlRunnable =
new RemoteBlobControlRunnable(mWorkerPrivate, aRunnable);
if (!controlRunnable->Dispatch()) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}
nsCOMPtr<nsIEventTarget> target = BaseRemoteBlobImpl()->GetActorEventTarget();
if (!target) {
target = do_GetMainThread();
}
MOZ_ASSERT(target);
return target->Dispatch(aRunnable, NS_DISPATCH_NORMAL);
}
void
BlobChild::
RemoteBlobImpl::WorkerHasNotified()
@ -2585,166 +2163,6 @@ RemoteBlobImpl::WorkerHasNotified()
mWorkerPrivate = nullptr;
}
/*******************************************************************************
* BlobChild::RemoteBlobImpl::CreateStreamHelper
******************************************************************************/
BlobChild::RemoteBlobImpl::
CreateStreamHelper::CreateStreamHelper(RemoteBlobImpl* aRemoteBlobImpl)
: mMonitor("BlobChild::RemoteBlobImpl::CreateStreamHelper::mMonitor")
, mRemoteBlobImpl(aRemoteBlobImpl)
, mStart(aRemoteBlobImpl->IsSlice() ? aRemoteBlobImpl->AsSlice()->Start() : 0)
, mLength(0)
, mDone(false)
{
// This may be created on any thread.
MOZ_ASSERT(aRemoteBlobImpl);
ErrorResult rv;
const_cast<uint64_t&>(mLength) = aRemoteBlobImpl->GetSize(rv);
MOZ_ASSERT(!rv.Failed());
}
nsresult
BlobChild::RemoteBlobImpl::
CreateStreamHelper::GetStream(nsIInputStream** aInputStream)
{
// This may be called on any thread.
MOZ_ASSERT(aInputStream);
MOZ_ASSERT(mRemoteBlobImpl);
MOZ_ASSERT(!mInputStream);
MOZ_ASSERT(!mDone);
RefPtr<RemoteBlobImpl> baseRemoteBlobImpl =
mRemoteBlobImpl->BaseRemoteBlobImpl();
MOZ_ASSERT(baseRemoteBlobImpl);
if (EventTargetIsOnCurrentThread(baseRemoteBlobImpl->GetActorEventTarget())) {
// RunInternal will populate mInputStream using the correct mStart/mLength
// value.
RunInternal(baseRemoteBlobImpl, false);
} else if (PBackgroundChild* manager = mozilla::ipc::BackgroundChild::GetForCurrentThread()) {
// In case we are on a PBackground thread and this is not the owning thread,
// we need to create a new actor here. This actor must be created for the
// baseRemoteBlobImpl, which can be the mRemoteBlobImpl or the parent one,
// in case we are dealing with a sliced blob.
BlobChild* blobChild = BlobChild::GetOrCreate(manager, baseRemoteBlobImpl);
MOZ_ASSERT(blobChild);
// Note that baseBlobImpl is generated by the actor, and the actor is
// created from the baseRemoteBlobImpl. This means that baseBlobImpl is the
// remote blobImpl on PBackground of baseRemoteBlobImpl.
RefPtr<BlobImpl> baseBlobImpl = blobChild->GetBlobImpl();
MOZ_ASSERT(baseBlobImpl);
ErrorResult rv;
nsCOMPtr<nsIInputStream> baseInputStream;
baseBlobImpl->GetInternalStream(getter_AddRefs(baseInputStream), rv);
if (NS_WARN_IF(rv.Failed())) {
return rv.StealNSResult();
}
// baseInputStream is the stream of the baseRemoteBlobImpl. If
// mRemoteBlobImpl is a slice of baseRemoteBlobImpl, here we need to slice
// baseInputStream.
if (mRemoteBlobImpl->IsSlice()) {
RefPtr<SlicedInputStream> slicedInputStream =
new SlicedInputStream(baseInputStream, mStart, mLength);
slicedInputStream.forget(aInputStream);
} else {
baseInputStream.forget(aInputStream);
}
mRemoteBlobImpl = nullptr;
mDone = true;
return NS_OK;
} else {
nsresult rv = baseRemoteBlobImpl->DispatchToTarget(this);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
DebugOnly<bool> warned = false;
{
MonitorAutoLock lock(mMonitor);
while (!mDone) {
#ifdef DEBUG
if (!warned) {
NS_WARNING("RemoteBlobImpl::GetInternalStream() called on thread "
"that can't send messages, blocking here to wait for the "
"actor's thread to send the message!");
}
#endif
lock.Wait();
}
}
}
MOZ_ASSERT(!mRemoteBlobImpl);
MOZ_ASSERT(mDone);
if (!mInputStream) {
return NS_ERROR_UNEXPECTED;
}
mInputStream.forget(aInputStream);
return NS_OK;
}
void
BlobChild::RemoteBlobImpl::
CreateStreamHelper::RunInternal(RemoteBlobImpl* aBaseRemoteBlobImpl,
bool aNotify)
{
MOZ_ASSERT(aBaseRemoteBlobImpl);
MOZ_ASSERT(aBaseRemoteBlobImpl->ActorEventTargetIsOnCurrentThread());
MOZ_ASSERT(!mInputStream);
MOZ_ASSERT(!mDone);
if (BlobChild* actor = aBaseRemoteBlobImpl->GetActor()) {
RefPtr<RemoteInputStream> stream;
if (!NS_IsMainThread() && GetCurrentThreadWorkerPrivate()) {
stream =
new RemoteInputStream(actor, mRemoteBlobImpl, mStart, mLength);
} else {
stream = new RemoteInputStream(mRemoteBlobImpl, mStart, mLength);
}
auto* streamActor = new InputStreamChild(stream);
if (actor->SendPBlobStreamConstructor(streamActor, mStart, mLength)) {
stream.swap(mInputStream);
}
}
mRemoteBlobImpl = nullptr;
if (aNotify) {
MonitorAutoLock lock(mMonitor);
mDone = true;
lock.Notify();
} else {
mDone = true;
}
}
NS_IMETHODIMP
BlobChild::RemoteBlobImpl::
CreateStreamHelper::Run()
{
MOZ_ASSERT(mRemoteBlobImpl);
MOZ_ASSERT(mRemoteBlobImpl->ActorEventTargetIsOnCurrentThread());
RefPtr<RemoteBlobImpl> baseRemoteBlobImpl =
mRemoteBlobImpl->BaseRemoteBlobImpl();
MOZ_ASSERT(baseRemoteBlobImpl);
RunInternal(baseRemoteBlobImpl, true);
return NS_OK;
}
/*******************************************************************************
* BlobChild::RemoteBlobSliceImpl
******************************************************************************/
@ -3828,24 +3246,6 @@ BlobChild::ActorDestroy(ActorDestroyReason aWhy)
#endif
}
PBlobStreamChild*
BlobChild::AllocPBlobStreamChild(const uint64_t& aStart,
const uint64_t& aLength)
{
AssertIsOnOwningThread();
return new InputStreamChild();
}
bool
BlobChild::DeallocPBlobStreamChild(PBlobStreamChild* aActor)
{
AssertIsOnOwningThread();
delete static_cast<InputStreamChild*>(aActor);
return true;
}
mozilla::ipc::IPCResult
BlobChild::RecvCreatedFromKnownBlob()
{
@ -4380,28 +3780,6 @@ BlobParent::NoteDyingRemoteBlobImpl()
Unused << PBlobParent::Send__delete__(this);
}
void
BlobParent::NoteRunnableCompleted(OpenStreamRunnable* aRunnable)
{
AssertIsOnOwningThread();
MOZ_ASSERT(aRunnable);
for (uint32_t count = mOpenStreamRunnables.Length(), index = 0;
index < count;
index++) {
nsRevocableEventPtr<OpenStreamRunnable>& runnable =
mOpenStreamRunnables[index];
if (runnable.get() == aRunnable) {
runnable.Forget();
mOpenStreamRunnables.RemoveElementAt(index);
return;
}
}
MOZ_CRASH("Runnable not in our array!");
}
bool
BlobParent::IsOnOwningThread() const
{
@ -4430,139 +3808,6 @@ BlobParent::ActorDestroy(ActorDestroyReason aWhy)
#endif
}
PBlobStreamParent*
BlobParent::AllocPBlobStreamParent(const uint64_t& aStart,
const uint64_t& aLength)
{
AssertIsOnOwningThread();
if (NS_WARN_IF(mRemoteBlobImpl)) {
ASSERT_UNLESS_FUZZING();
return nullptr;
}
return new InputStreamParent();
}
mozilla::ipc::IPCResult
BlobParent::RecvPBlobStreamConstructor(PBlobStreamParent* aActor,
const uint64_t& aStart,
const uint64_t& aLength)
{
AssertIsOnOwningThread();
MOZ_ASSERT(aActor);
MOZ_ASSERT(mBlobImpl);
MOZ_ASSERT(!mRemoteBlobImpl);
MOZ_ASSERT(mOwnsBlobImpl);
auto* actor = static_cast<InputStreamParent*>(aActor);
// Make sure we can't overflow.
if (NS_WARN_IF(UINT64_MAX - aLength < aStart)) {
ASSERT_UNLESS_FUZZING();
return IPC_FAIL_NO_REASON(this);
}
ErrorResult errorResult;
uint64_t blobLength = mBlobImpl->GetSize(errorResult);
MOZ_ASSERT(!errorResult.Failed());
if (NS_WARN_IF(aStart + aLength > blobLength)) {
ASSERT_UNLESS_FUZZING();
return IPC_FAIL_NO_REASON(this);
}
RefPtr<BlobImpl> blobImpl;
if (!aStart && aLength == blobLength) {
blobImpl = mBlobImpl;
} else {
nsString type;
mBlobImpl->GetType(type);
blobImpl = mBlobImpl->CreateSlice(aStart, aLength, type, errorResult);
if (NS_WARN_IF(errorResult.Failed())) {
return IPC_FAIL_NO_REASON(this);
}
}
nsCOMPtr<nsIInputStream> stream;
blobImpl->GetInternalStream(getter_AddRefs(stream), errorResult);
if (NS_WARN_IF(errorResult.Failed())) {
return IPC_FAIL_NO_REASON(this);
}
// If the stream is entirely backed by memory then we can serialize and send
// it immediately.
if (mBlobImpl->IsMemoryFile()) {
InputStreamParams params;
nsTArray<FileDescriptor> fds;
InputStreamHelper::SerializeInputStream(stream, params, fds);
MOZ_ASSERT(params.type() != InputStreamParams::T__None);
MOZ_ASSERT(fds.IsEmpty());
if (!actor->Destroy(params, void_t())) {
return IPC_FAIL_NO_REASON(this);
}
return IPC_OK();
}
nsCOMPtr<nsIRemoteBlob> remoteBlob = do_QueryInterface(mBlobImpl);
nsCOMPtr<IPrivateRemoteInputStream> remoteStream;
if (remoteBlob) {
remoteStream = do_QueryInterface(stream);
}
// There are three cases in which we can use the stream obtained from the blob
// directly as our serialized stream:
//
// 1. The blob is not a remote blob.
// 2. The blob is a remote blob that represents this actor.
// 3. The blob is a remote blob representing a different actor but we
// already have a non-remote, i.e. serialized, serialized stream.
//
// In all other cases we need to be on a background thread before we can get
// to the real stream.
nsCOMPtr<nsIIPCSerializableInputStream> serializableStream;
if (!remoteBlob ||
remoteBlob->GetBlobParent() == this ||
!remoteStream) {
serializableStream = do_QueryInterface(stream);
if (!serializableStream) {
MOZ_ASSERT(false, "Must be serializable!");
return IPC_FAIL_NO_REASON(this);
}
}
nsCOMPtr<nsIThread> target;
errorResult = NS_NewNamedThread("Blob Opener", getter_AddRefs(target));
if (NS_WARN_IF(errorResult.Failed())) {
return IPC_FAIL_NO_REASON(this);
}
RefPtr<OpenStreamRunnable> runnable =
new OpenStreamRunnable(this, actor, stream, serializableStream, target);
errorResult = runnable->Dispatch();
if (NS_WARN_IF(errorResult.Failed())) {
return IPC_FAIL_NO_REASON(this);
}
// nsRevocableEventPtr lacks some of the operators needed for anything nicer.
*mOpenStreamRunnables.AppendElement() = runnable;
return IPC_OK();
}
bool
BlobParent::DeallocPBlobStreamParent(PBlobStreamParent* aActor)
{
AssertIsOnOwningThread();
delete static_cast<InputStreamParent*>(aActor);
return true;
}
mozilla::ipc::IPCResult
BlobParent::RecvResolveMystery(const ResolveMysteryParams& aParams)
{
@ -4621,44 +3866,6 @@ BlobParent::RecvResolveMystery(const ResolveMysteryParams& aParams)
MOZ_CRASH("Should never get here!");
}
mozilla::ipc::IPCResult
BlobParent::RecvBlobStreamSync(const uint64_t& aStart,
const uint64_t& aLength,
InputStreamParams* aParams,
OptionalFileDescriptorSet* aFDs)
{
AssertIsOnOwningThread();
MOZ_ASSERT(mBlobImpl);
MOZ_ASSERT(!mRemoteBlobImpl);
MOZ_ASSERT(mOwnsBlobImpl);
bool finished = false;
{
// Calling RecvPBlobStreamConstructor() may synchronously delete the actor
// we pass in so don't touch it outside this block.
auto* streamActor = new InputStreamParent(&finished, aParams, aFDs);
if (NS_WARN_IF(!RecvPBlobStreamConstructor(streamActor, aStart, aLength))) {
// If RecvPBlobStreamConstructor() returns false then it is our
// responsibility to destroy the actor.
delete streamActor;
return IPC_FAIL_NO_REASON(this);
}
}
if (finished) {
// The actor is already dead and we have already set our out params.
return IPC_OK();
}
// The actor is alive and will be doing asynchronous work to load the stream.
// Spin a nested loop here while we wait for it.
MOZ_ALWAYS_TRUE(SpinEventLoopUntil([&]() { return finished; }));
return IPC_OK();
}
mozilla::ipc::IPCResult
BlobParent::RecvWaitForSliceCreation()
{
@ -4813,30 +4020,5 @@ IDTableEntry::GetOrCreateInternal(const nsID& aID,
return entry.forget();
}
/*******************************************************************************
* Other stuff
******************************************************************************/
mozilla::ipc::IPCResult
InputStreamChild::Recv__delete__(const InputStreamParams& aParams,
const OptionalFileDescriptorSet& aOptionalSet)
{
MOZ_ASSERT(mRemoteStream);
mRemoteStream->AssertIsOnOwningThread();
nsTArray<FileDescriptor> fds;
OptionalFileDescriptorSetToFDs(
// XXX Fix this somehow...
const_cast<OptionalFileDescriptorSet&>(aOptionalSet),
fds);
nsCOMPtr<nsIInputStream> stream =
InputStreamHelper::DeserializeInputStream(aParams, fds);
MOZ_ASSERT(stream);
mRemoteStream->SetStream(stream);
return IPC_OK();
}
} // namespace dom
} // namespace mozilla

View File

@ -29,7 +29,6 @@ class Blob;
class BlobImpl;
class ContentChild;
class nsIContentChild;
class PBlobStreamChild;
class BlobChild final
: public PBlobChild
@ -211,13 +210,6 @@ private:
virtual void
ActorDestroy(ActorDestroyReason aWhy) override;
virtual PBlobStreamChild*
AllocPBlobStreamChild(const uint64_t& aStart,
const uint64_t& aLength) override;
virtual bool
DeallocPBlobStreamChild(PBlobStreamChild* aActor) override;
virtual mozilla::ipc::IPCResult
RecvCreatedFromKnownBlob() override;
};

View File

@ -35,7 +35,6 @@ namespace dom {
class ContentParent;
class BlobImpl;
class nsIContentParent;
class PBlobStreamParent;
class BlobParent final
: public PBlobParent
@ -45,9 +44,6 @@ class BlobParent final
class IDTableEntry;
typedef nsDataHashtable<nsIDHashKey, IDTableEntry*> IDTable;
class OpenStreamRunnable;
friend class OpenStreamRunnable;
class RemoteBlobImpl;
struct CreateBlobImplMetadata;
@ -64,15 +60,6 @@ class BlobParent final
nsCOMPtr<nsIEventTarget> mEventTarget;
// nsIInputStreams backed by files must ensure that the files are actually
// opened and closed on a background thread before we can send their file
// handles across to the child. The child process could crash during this
// process so we need to make sure we cancel the intended response in such a
// case. We do that by holding an array of nsRevocableEventPtr. If the child
// crashes then this actor will be destroyed and the nsRevocableEventPtr
// destructor will cancel any stream events that are currently in flight.
nsTArray<nsRevocableEventPtr<OpenStreamRunnable>> mOpenStreamRunnables;
RefPtr<IDTableEntry> mIDTableEntry;
bool mOwnsBlobImpl;
@ -189,9 +176,6 @@ private:
void
NoteDyingRemoteBlobImpl();
void
NoteRunnableCompleted(OpenStreamRunnable* aRunnable);
nsIEventTarget*
EventTarget() const
{
@ -205,27 +189,9 @@ private:
virtual void
ActorDestroy(ActorDestroyReason aWhy) override;
virtual PBlobStreamParent*
AllocPBlobStreamParent(const uint64_t& aStart,
const uint64_t& aLength) override;
virtual mozilla::ipc::IPCResult
RecvPBlobStreamConstructor(PBlobStreamParent* aActor,
const uint64_t& aStart,
const uint64_t& aLength) override;
virtual bool
DeallocPBlobStreamParent(PBlobStreamParent* aActor) override;
virtual mozilla::ipc::IPCResult
RecvResolveMystery(const ResolveMysteryParams& aParams) override;
virtual mozilla::ipc::IPCResult
RecvBlobStreamSync(const uint64_t& aStart,
const uint64_t& aLength,
InputStreamParams* aParams,
OptionalFileDescriptorSet* aFDs) override;
virtual mozilla::ipc::IPCResult
RecvWaitForSliceCreation() override;

View File

@ -3,7 +3,6 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
include protocol PBackground;
include protocol PBlobStream;
include protocol PContent;
include protocol PContentBridge;
include protocol PFileDescriptorSet;
@ -26,19 +25,13 @@ union ResolveMysteryParams
sync protocol PBlob
{
manager PBackground or PContent or PContentBridge;
manages PBlobStream;
both:
async __delete__();
parent:
async PBlobStream(uint64_t begin, uint64_t length);
async ResolveMystery(ResolveMysteryParams params);
sync BlobStreamSync(uint64_t begin, uint64_t length)
returns (InputStreamParams params, OptionalFileDescriptorSet fds);
sync WaitForSliceCreation();
// Use only for testing!

View File

@ -1,22 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
include protocol PBlob;
include protocol PFileDescriptorSet;
include BlobTypes;
include InputStreamParams;
namespace mozilla {
namespace dom {
protocol PBlobStream
{
manager PBlob;
child:
async __delete__(InputStreamParams params, OptionalFileDescriptorSet fds);
};
} // namespace dom
} // namespace mozilla

View File

@ -35,7 +35,6 @@ IPDL_SOURCES += [
'BlobTypes.ipdlh',
'IPCBlob.ipdlh',
'PBlob.ipdl',
'PBlobStream.ipdl',
'PIPCBlobInputStream.ipdl',
'PPendingIPCBlob.ipdl',
]

View File

@ -807,8 +807,6 @@ description =
# The rest
[PHeapSnapshotTempFileHelper::OpenHeapSnapshotTempFile]
description =
[PBlob::BlobStreamSync]
description =
[PBlob::WaitForSliceCreation]
description =
[PBlob::GetFileId]