Bug 1754004 - Part 3: Move RemoteLazyInputStream to its own toplevel protocol, r=asuth,necko-reviewers,dragana

This is a complete rewrite of RemoteLazyInputStream to run off of its own
toplevel protocol, rather than being managed by other protocols like
PBackground or PContent. This should improve performance thanks to no longer
needing to operate on a main or worker thread, and due to no longer needing the
migration step for the stream actor.

This also acts as a step towards no longer requiring a manager actor to
serialize input streams, as the type is now actor-agnostic, and should support
being sent over IPC between any pair of processes.

Differential Revision: https://phabricator.services.mozilla.com/D141040
This commit is contained in:
Nika Layzell 2022-05-10 22:27:42 +00:00
parent 728ba534f6
commit 76cdaba44a
60 changed files with 1149 additions and 1720 deletions

View File

@ -3,7 +3,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
include protocol PBackground;
include protocol PRemoteLazyInputStream; // FIXME: bug 792908
include DOMTypes;

View File

@ -4,7 +4,6 @@
include protocol PClientManager;
include protocol PClientHandleOp;
include protocol PRemoteLazyInputStream;
include ClientIPCTypes;
include "mozilla/ipc/ProtocolMessageUtils.h";

View File

@ -7,7 +7,6 @@ include protocol PClientHandle;
include protocol PClientManagerOp;
include protocol PClientNavigateOp;
include protocol PClientSource;
include protocol PRemoteLazyInputStream;
include ClientIPCTypes;
namespace mozilla {

View File

@ -4,7 +4,6 @@
include protocol PClientManager;
include protocol PClientSourceOp;
include protocol PRemoteLazyInputStream;
include ClientIPCTypes;
namespace mozilla {

View File

@ -7,7 +7,6 @@
#include "mozilla/NotNull.h"
#include "mozilla/RemoteLazyInputStreamChild.h"
#include "mozilla/RemoteLazyInputStreamStorage.h"
#include "mozilla/RemoteLazyInputStreamUtils.h"
#include "mozilla/dom/FetchTypes.h"
#include "mozilla/dom/IPCBlob.h"
#include "nsContentUtils.h"
@ -35,9 +34,7 @@ NotNull<nsCOMPtr<nsIInputStream>> ToInputStream(
NotNull<nsCOMPtr<nsIInputStream>> ToInputStream(
const ParentToChildStream& aStream) {
MOZ_ASSERT(XRE_IsContentProcess());
nsCOMPtr<nsIInputStream> result =
static_cast<RemoteLazyInputStreamChild*>(aStream.actorChild())
->CreateStream();
nsCOMPtr<nsIInputStream> result = aStream.stream();
return WrapNotNull(result);
}
@ -47,8 +44,7 @@ ParentToParentStream ToParentToParentStream(
ParentToParentStream stream;
stream.uuid() = nsID::GenerateUUID();
GetRemoteLazyInputStreamStorage()->AddStream(aStream.get(), stream.uuid(),
aStreamSize, 0);
GetRemoteLazyInputStreamStorage()->AddStream(aStream.get(), stream.uuid());
return stream;
}
@ -58,10 +54,7 @@ ParentToChildStream ToParentToChildStream(
MOZ_ASSERT(XRE_IsParentProcess());
ParentToChildStream result;
RemoteLazyStream remoteLazyStream;
MOZ_ALWAYS_SUCCEEDS(RemoteLazyInputStreamUtils::SerializeInputStream(
aStream.get(), aStreamSize, remoteLazyStream, aBackgroundParent));
result.actorParent() = remoteLazyStream;
result.stream() = RemoteLazyInputStream::WrapStream(aStream.get());
return result;
}

View File

@ -7,8 +7,6 @@ include IPCChannelInfo;
include PBackgroundSharedTypes;
include PerformanceTimingTypes;
include protocol PRemoteLazyInputStream;
include "mozilla/dom/FetchIPCTypes.h";
using HeadersGuardEnum from "mozilla/dom/HeadersBinding.h";
@ -19,6 +17,7 @@ using RequestMode from "mozilla/dom/RequestBinding.h";
using RequestRedirect from "mozilla/dom/RequestBinding.h";
using ResponseType from "mozilla/dom/ResponseBinding.h";
using struct nsID from "nsID.h";
[RefCounted] using class mozilla::RemoteLazyInputStream from "mozilla/RemoteLazyInputStream.h";
namespace mozilla {
namespace dom {
@ -34,7 +33,7 @@ struct ParentToParentStream {
};
struct ParentToChildStream {
PRemoteLazyInputStream actor;
RemoteLazyInputStream stream;
};
struct ChildToParentStream {

View File

@ -171,9 +171,7 @@ InternalRequest::InternalRequest(const IPCInternalRequest& aIPCRequest)
// (constructed on the child side).
if (body) {
MOZ_ASSERT(body->type() == BodyStreamVariant::TParentToChildStream);
mBodyStream = static_cast<RemoteLazyInputStreamChild*>(
body->get_ParentToChildStream().actorChild())
->CreateStream();
mBodyStream = body->get_ParentToChildStream().stream();
}
}

View File

@ -2,12 +2,11 @@
* 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 PRemoteLazyInputStream;
include IPCStream;
include ProtocolTypes;
using struct mozilla::void_t from "mozilla/ipc/IPCCore.h";
[RefCounted] using class mozilla::RemoteLazyInputStream from "mozilla/RemoteLazyInputStream.h";
namespace mozilla {
@ -15,7 +14,7 @@ union RemoteLazyStream
{
// Parent to Child: The child will receive a RemoteLazyInputStream. Nothing
// can be done with it except retrieving the size.
PRemoteLazyInputStream;
RemoteLazyInputStream;
// Child to Parent: Normal serialization.
IPCStream;

View File

@ -8,7 +8,6 @@
#include "RemoteLazyInputStream.h"
#include "RemoteLazyInputStreamChild.h"
#include "RemoteLazyInputStreamParent.h"
#include "RemoteLazyInputStreamUtils.h"
#include "mozilla/dom/IPCBlob.h"
#include "mozilla/ipc/BackgroundParent.h"
#include "mozilla/ipc/PBackgroundParent.h"
@ -34,11 +33,8 @@ already_AddRefed<BlobImpl> Deserialize(const IPCBlob& aIPCBlob) {
switch (stream.type()) {
// Parent to child: when an nsIInputStream is sent from parent to child, the
// child receives a RemoteLazyInputStream actor.
case RemoteLazyStream::TPRemoteLazyInputStreamChild: {
RemoteLazyInputStreamChild* actor =
static_cast<RemoteLazyInputStreamChild*>(
stream.get_PRemoteLazyInputStreamChild());
inputStream = actor->CreateStream();
case RemoteLazyStream::TRemoteLazyInputStream: {
inputStream = stream.get_RemoteLazyInputStream();
break;
}
@ -129,14 +125,23 @@ nsresult SerializeInternal(BlobImpl* aBlobImpl, M* aManager,
return rv.StealNSResult();
}
RemoteLazyStream stream;
rv = RemoteLazyInputStreamUtils::SerializeInputStream(
inputStream, aIPCBlob.size(), stream, aManager);
if (NS_WARN_IF(rv.Failed())) {
return rv.StealNSResult();
if (XRE_IsParentProcess()) {
RefPtr<RemoteLazyInputStream> stream =
RemoteLazyInputStream::WrapStream(inputStream);
if (NS_WARN_IF(!stream)) {
return rv.StealNSResult();
}
aIPCBlob.inputStream() = stream;
return NS_OK;
}
aIPCBlob.inputStream() = stream;
mozilla::ipc::AutoIPCStream ipcStream(true /* delayed start */);
if (!ipcStream.Serialize(inputStream, aManager)) {
return NS_ERROR_FAILURE;
}
aIPCBlob.inputStream() = ipcStream.TakeValue();
return NS_OK;
}

View File

@ -3,7 +3,6 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
include protocol PBackground;
include protocol PRemoteLazyInputStream;
include IPCBlob;

View File

@ -2,42 +2,20 @@
* 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 PBackground;
include protocol PContent;
include protocol PSocketProcess;
include IPCStream;
namespace mozilla {
protocol PRemoteLazyInputStream
{
manager PBackground or PContent or PSocketProcess;
parent:
async StreamNeeded();
async Clone(Endpoint<PRemoteLazyInputStreamParent> aCloneEndpoint);
async LengthNeeded();
async StreamNeeded(uint64_t aStart, uint64_t aLength) returns (IPCStream? stream);
// When this is called, the parent releases the inputStream and sends a
// __delete__.
async Close();
async LengthNeeded() returns (int64_t length);
child:
async StreamReady(IPCStream? aStream);
async LengthReady(int64_t aLength);
both:
// __delete__ can be called by parent and by child for 2 reasons:
// - parent->child: This happens after a Close(). The child wants to inform
// the parent that no other messages will be dispatched and
// that the channel can be interrupted.
// - child->parent: before any operation, the child could start a migration
// from the current thread to a dedicated DOM-File one. The
// reason why a __delete__ is sent from child to parent is
// because it doesn't require any additional runnables.
async __delete__();
async Goodbye();
};
} // namespace mozilla

View File

@ -3,7 +3,6 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
include protocol PBackground;
include protocol PRemoteLazyInputStream;
include IPCBlob;
@ -37,5 +36,5 @@ parent:
async OperationDone(nsCString aContentType, FileDescriptor aFD);
};
} // namespace dom
} // namespace dom
} // namespace mozilla

File diff suppressed because it is too large Load Diff

View File

@ -7,6 +7,7 @@
#ifndef mozilla_RemoteLazyInputStream_h
#define mozilla_RemoteLazyInputStream_h
#include "chrome/common/ipc_message_utils.h"
#include "mozilla/Mutex.h"
#include "mozIRemoteLazyInputStream.h"
#include "nsIAsyncInputStream.h"
@ -41,34 +42,56 @@ class RemoteLazyInputStream final : public nsIAsyncInputStream,
NS_DECL_NSIINPUTSTREAMLENGTH
NS_DECL_NSIASYNCINPUTSTREAMLENGTH
explicit RemoteLazyInputStream(RemoteLazyInputStreamChild* aActor);
void StreamReady(already_AddRefed<nsIInputStream> aInputStream);
void LengthReady(int64_t aLength);
// Create a new lazy RemoteLazyInputStream, and move the provided aInputStream
// into storage as referenced by it. May only be called in processes with
// RemoteLazyInputStreamStorage.
static already_AddRefed<RemoteLazyInputStream> WrapStream(
nsIInputStream* aInputStream);
// mozIRemoteLazyInputStream
NS_IMETHOD_(nsIInputStream*) GetInternalStream() override {
if (mRemoteStream) {
return mRemoteStream;
}
if (mAsyncRemoteStream) {
return mAsyncRemoteStream;
}
return nullptr;
}
NS_IMETHOD TakeInternalStream(nsIInputStream** aStream) override;
NS_IMETHOD GetInternalStreamID(nsID& aID) override;
private:
friend struct IPC::ParamTraits<mozilla::RemoteLazyInputStream*>;
// Constructor for an already-closed RemoteLazyInputStream.
RemoteLazyInputStream() = default;
explicit RemoteLazyInputStream(RemoteLazyInputStreamChild* aActor,
uint64_t aStart = 0,
uint64_t aLength = UINT64_MAX);
explicit RemoteLazyInputStream(nsIInputStream* aStream);
~RemoteLazyInputStream();
nsresult EnsureAsyncRemoteStream(const MutexAutoLock& aProofOfLock);
void StreamNeeded() REQUIRES(mMutex);
void InitWithExistingRange(uint64_t aStart, uint64_t aLength,
const MutexAutoLock& aProofOfLock);
// Upon receiving the stream from our actor, we will not wrap it into an async
// stream until needed. This allows callers to get access to the underlying
// potentially-sync stream using `TakeInternalStream` before reading.
nsresult EnsureAsyncRemoteStream() REQUIRES(mMutex);
RefPtr<RemoteLazyInputStreamChild> mActor;
// Note that data has been read from our input stream, and disconnect from our
// remote actor.
void MarkConsumed();
void IPCWrite(IPC::MessageWriter* aWriter);
static already_AddRefed<RemoteLazyInputStream> IPCRead(
IPC::MessageReader* aReader);
// Helper method to generate a description of a stream for use in loggging.
nsCString Describe() REQUIRES(mMutex);
// Start and length of the slice to apply on this RemoteLazyInputStream when
// fetching the underlying stream with `SendStreamNeeded`.
const uint64_t mStart = 0;
const uint64_t mLength = UINT64_MAX;
// Any non-const member of this class is protected by mutex because it is
// touched on multiple threads.
Mutex mMutex{"RemoteLazyInputStream::mMutex"};
// This is the list of possible states.
enum {
@ -81,43 +104,49 @@ class RemoteLazyInputStream final : public nsIAsyncInputStream,
ePending,
// When the child receives the stream from the parent, we move to this
// state. The received stream is stored in mRemoteStream. From now on, any
// method call will be forwared to mRemoteStream.
// state. The received stream is stored in mInnerStream. From now on, any
// method call will be forwared to mInnerStream or mAsyncInnerStream.
eRunning,
// If Close() or CloseWithStatus() is called, we move to this state.
// mRemoveStream is released and any method will return
// mInnerStream is released and any method will return
// NS_BASE_STREAM_CLOSED.
eClosed,
} mState;
} mState GUARDED_BY(mMutex) = eClosed;
uint64_t mStart;
uint64_t mLength;
// The actor which will be used to provide the underlying stream or length
// information when needed, as well as to efficiently allow transferring the
// stream over IPC.
//
// The connection to our actor will be cleared once the stream has been closed
// or has started reading, at which point this stream will be serialized and
// cloned as-if it was the underlying stream.
RefPtr<RemoteLazyInputStreamChild> mActor GUARDED_BY(mMutex);
// Set to true if the stream is used via Read/ReadSegments or Close.
bool mConsumed;
nsCOMPtr<nsIInputStream> mInnerStream GUARDED_BY(mMutex);
nsCOMPtr<nsIAsyncInputStream> mAsyncInnerStream GUARDED_BY(mMutex);
nsCOMPtr<nsIInputStream> mRemoteStream;
nsCOMPtr<nsIAsyncInputStream> mAsyncRemoteStream;
// These 2 values are set only if mState is ePending or eRunning.
// RefPtr is used instead of nsCOMPtr to avoid invoking QueryInterface when
// assigning in debug builds, as `mInputStreamCallback` may not be threadsafe.
RefPtr<nsIInputStreamCallback> mInputStreamCallback GUARDED_BY(mMutex);
nsCOMPtr<nsIEventTarget> mInputStreamCallbackEventTarget GUARDED_BY(mMutex);
uint32_t mInputStreamCallbackFlags GUARDED_BY(mMutex) = 0;
uint32_t mInputStreamCallbackRequestedCount GUARDED_BY(mMutex) = 0;
// These 2 values are set only if mState is ePending.
nsCOMPtr<nsIInputStreamCallback> mInputStreamCallback;
nsCOMPtr<nsIEventTarget> mInputStreamCallbackEventTarget;
// These 2 values are set only if mState is ePending.
nsCOMPtr<nsIFileMetadataCallback> mFileMetadataCallback;
nsCOMPtr<nsIEventTarget> mFileMetadataCallbackEventTarget;
// These 2 values are set only when nsIAsyncInputStreamLength::asyncWait() is
// called.
nsCOMPtr<nsIInputStreamLengthCallback> mLengthCallback;
nsCOMPtr<nsIEventTarget> mLengthCallbackEventTarget;
// Any member of this class is protected by mutex because touched on
// multiple threads.
Mutex mMutex MOZ_UNANNOTATED;
nsCOMPtr<nsIFileMetadataCallback> mFileMetadataCallback GUARDED_BY(mMutex);
nsCOMPtr<nsIEventTarget> mFileMetadataCallbackEventTarget GUARDED_BY(mMutex);
};
} // namespace mozilla
template <>
struct IPC::ParamTraits<mozilla::RemoteLazyInputStream*> {
static void Write(IPC::MessageWriter* aWriter,
mozilla::RemoteLazyInputStream* aParam);
static bool Read(IPC::MessageReader* aReader,
RefPtr<mozilla::RemoteLazyInputStream>* aResult);
};
#endif // mozilla_RemoteLazyInputStream_h

View File

@ -7,442 +7,44 @@
#include "RemoteLazyInputStreamChild.h"
#include "RemoteLazyInputStreamThread.h"
#include "mozilla/ipc/IPCStreamUtils.h"
#include "mozilla/dom/WorkerCommon.h"
#include "mozilla/dom/WorkerRef.h"
namespace mozilla {
using namespace dom;
extern mozilla::LazyLogModule gRemoteLazyStreamLog;
namespace {
// This runnable is used in case the last stream is forgotten on the 'wrong'
// thread.
class ShutdownRunnable final : public DiscardableRunnable {
public:
explicit ShutdownRunnable(RemoteLazyInputStreamChild* aActor)
: DiscardableRunnable("dom::ShutdownRunnable"), mActor(aActor) {}
NS_IMETHOD
Run() override {
mActor->Shutdown();
return NS_OK;
}
private:
RefPtr<RemoteLazyInputStreamChild> mActor;
};
// This runnable is used in case StreamNeeded() has been called on a non-owning
// thread.
class StreamNeededRunnable final : public DiscardableRunnable {
public:
explicit StreamNeededRunnable(RemoteLazyInputStreamChild* aActor)
: DiscardableRunnable("dom::StreamNeededRunnable"), mActor(aActor) {}
NS_IMETHOD
Run() override {
MOZ_ASSERT(
mActor->State() != RemoteLazyInputStreamChild::eActiveMigrating &&
mActor->State() != RemoteLazyInputStreamChild::eInactiveMigrating);
if (mActor->State() == RemoteLazyInputStreamChild::eActive) {
mActor->SendStreamNeeded();
}
return NS_OK;
}
private:
RefPtr<RemoteLazyInputStreamChild> mActor;
};
// When the stream has been received from the parent, we inform the
// RemoteLazyInputStream.
class StreamReadyRunnable final : public DiscardableRunnable {
public:
StreamReadyRunnable(RemoteLazyInputStream* aDestinationStream,
already_AddRefed<nsIInputStream> aCreatedStream)
: DiscardableRunnable("dom::StreamReadyRunnable"),
mDestinationStream(aDestinationStream),
mCreatedStream(std::move(aCreatedStream)) {
MOZ_ASSERT(mDestinationStream);
// mCreatedStream can be null.
}
NS_IMETHOD
Run() override {
mDestinationStream->StreamReady(mCreatedStream.forget());
return NS_OK;
}
private:
RefPtr<RemoteLazyInputStream> mDestinationStream;
nsCOMPtr<nsIInputStream> mCreatedStream;
};
// This runnable is used in case LengthNeeded() has been called on a non-owning
// thread.
class LengthNeededRunnable final : public DiscardableRunnable {
public:
explicit LengthNeededRunnable(RemoteLazyInputStreamChild* aActor)
: DiscardableRunnable("dom::LengthNeededRunnable"), mActor(aActor) {}
NS_IMETHOD
Run() override {
MOZ_ASSERT(
mActor->State() != RemoteLazyInputStreamChild::eActiveMigrating &&
mActor->State() != RemoteLazyInputStreamChild::eInactiveMigrating);
if (mActor->State() == RemoteLazyInputStreamChild::eActive) {
mActor->SendLengthNeeded();
}
return NS_OK;
}
private:
RefPtr<RemoteLazyInputStreamChild> mActor;
};
// When the stream has been received from the parent, we inform the
// RemoteLazyInputStream.
class LengthReadyRunnable final : public DiscardableRunnable {
public:
LengthReadyRunnable(RemoteLazyInputStream* aDestinationStream, int64_t aSize)
: DiscardableRunnable("dom::LengthReadyRunnable"),
mDestinationStream(aDestinationStream),
mSize(aSize) {
MOZ_ASSERT(mDestinationStream);
}
NS_IMETHOD
Run() override {
mDestinationStream->LengthReady(mSize);
return NS_OK;
}
private:
RefPtr<RemoteLazyInputStream> mDestinationStream;
int64_t mSize;
};
} // namespace
RemoteLazyInputStreamChild::RemoteLazyInputStreamChild(const nsID& aID,
uint64_t aSize)
: mMutex("RemoteLazyInputStreamChild::mMutex"),
mID(aID),
mSize(aSize),
mState(eActive),
mOwningEventTarget(GetCurrentSerialEventTarget()) {
// If we are running in a worker, we need to send a Close() to the parent side
// before the thread is released.
if (!NS_IsMainThread()) {
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
if (!workerPrivate) {
return;
}
RefPtr<StrongWorkerRef> workerRef =
StrongWorkerRef::Create(workerPrivate, "RemoteLazyInputStreamChild");
if (!workerRef) {
return;
}
// We must keep the worker alive until the migration is completed.
mWorkerRef = new ThreadSafeWorkerRef(workerRef);
}
}
RemoteLazyInputStreamChild::RemoteLazyInputStreamChild(const nsID& aID)
: mID(aID) {}
RemoteLazyInputStreamChild::~RemoteLazyInputStreamChild() = default;
void RemoteLazyInputStreamChild::Shutdown() {
RefPtr<RemoteLazyInputStreamChild> kungFuDeathGrip = this;
// Don't delete the pending operations inside our lock, since that might
// lead to a lock-ordering inversion
nsTArray<PendingOperation> pending;
{
MutexAutoLock lock(mMutex);
mWorkerRef = nullptr;
pending.SwapElements(mPendingOperations);
if (mState == eActive) {
SendClose();
mState = eInactive;
}
}
// Now release pending operations.
// We could let this be destroyed by scope, but I prefer
// to be explicit that we clear this before we drop the
// self-reference
pending.Clear();
void RemoteLazyInputStreamChild::StreamCreated() {
size_t count = ++mStreamCount;
MOZ_LOG(gRemoteLazyStreamLog, LogLevel::Verbose,
("Child::StreamCreated %s = %zu", nsIDToCString(mID).get(), count));
}
void RemoteLazyInputStreamChild::ActorDestroy(
IProtocol::ActorDestroyReason aReason) {
bool migrating = false;
void RemoteLazyInputStreamChild::StreamConsumed() {
size_t count = --mStreamCount;
MOZ_LOG(gRemoteLazyStreamLog, LogLevel::Verbose,
("Child::StreamConsumed %s = %zu", nsIDToCString(mID).get(), count));
{
MutexAutoLock lock(mMutex);
migrating = mState == eActiveMigrating;
mState = migrating ? eInactiveMigrating : eInactive;
}
if (!migrating) {
// Let's cleanup the workerRef and the pending operation queue.
Shutdown();
return;
// When the count reaches zero, close the underlying actor.
if (count == 0) {
RemoteLazyInputStreamThread::Get()->Dispatch(NS_NewRunnableFunction(
"RemoteLazyInputStreamChild::StreamConsumed", [self = RefPtr{this}]() {
if (self->CanSend()) {
self->SendGoodbye();
}
}));
}
}
RemoteLazyInputStreamChild::ActorState RemoteLazyInputStreamChild::State() {
MutexAutoLock lock(mMutex);
return mState;
}
already_AddRefed<RemoteLazyInputStream>
RemoteLazyInputStreamChild::CreateStream() {
bool shouldMigrate = false;
RefPtr<RemoteLazyInputStream> stream;
{
MutexAutoLock lock(mMutex);
if (mState == eInactive) {
return nullptr;
}
// The stream is active but maybe it is not running in the DOM-File thread.
// We should migrate it there.
if (mState == eActive &&
!RemoteLazyInputStreamThread::IsOnFileEventTarget(mOwningEventTarget)) {
MOZ_ASSERT(mStreams.IsEmpty());
shouldMigrate = true;
mState = eActiveMigrating;
RefPtr<RemoteLazyInputStreamThread> thread =
RemoteLazyInputStreamThread::GetOrCreate();
MOZ_ASSERT(thread, "We cannot continue without DOMFile thread.");
// Create a new actor object to connect to the target thread.
RefPtr<RemoteLazyInputStreamChild> newActor =
new RemoteLazyInputStreamChild(mID, mSize);
{
MutexAutoLock newActorLock(newActor->mMutex);
// Move over our local state onto the new actor object.
newActor->mWorkerRef = mWorkerRef;
newActor->mState = eInactiveMigrating;
newActor->mPendingOperations = std::move(mPendingOperations);
// Create the actual stream object.
stream = new RemoteLazyInputStream(newActor);
newActor->mStreams.AppendElement(stream);
}
// Perform the actual migration.
thread->MigrateActor(newActor);
} else {
stream = new RemoteLazyInputStream(this);
mStreams.AppendElement(stream);
}
}
// Send__delete__ will call ActorDestroy(). mMutex cannot be locked at this
// time.
if (shouldMigrate) {
Send__delete__(this);
}
return stream.forget();
}
void RemoteLazyInputStreamChild::ForgetStream(RemoteLazyInputStream* aStream) {
MOZ_ASSERT(aStream);
RefPtr<RemoteLazyInputStreamChild> kungFuDeathGrip = this;
{
MutexAutoLock lock(mMutex);
mStreams.RemoveElement(aStream);
if (!mStreams.IsEmpty() || mState != eActive) {
return;
}
}
if (mOwningEventTarget->IsOnCurrentThread()) {
Shutdown();
return;
}
RefPtr<ShutdownRunnable> runnable = new ShutdownRunnable(this);
mOwningEventTarget->Dispatch(runnable, NS_DISPATCH_NORMAL);
}
void RemoteLazyInputStreamChild::StreamNeeded(RemoteLazyInputStream* aStream,
nsIEventTarget* aEventTarget) {
MutexAutoLock lock(mMutex);
if (mState == eInactive) {
return;
}
MOZ_ASSERT(mStreams.Contains(aStream));
PendingOperation* opt = mPendingOperations.AppendElement();
opt->mStream = aStream;
opt->mEventTarget = aEventTarget;
opt->mOp = PendingOperation::eStreamNeeded;
if (mState == eActiveMigrating || mState == eInactiveMigrating) {
// This operation will be continued when the migration is completed.
return;
}
MOZ_ASSERT(mState == eActive);
if (mOwningEventTarget->IsOnCurrentThread()) {
SendStreamNeeded();
return;
}
RefPtr<StreamNeededRunnable> runnable = new StreamNeededRunnable(this);
mOwningEventTarget->Dispatch(runnable.forget(), NS_DISPATCH_NORMAL);
}
mozilla::ipc::IPCResult RemoteLazyInputStreamChild::RecvStreamReady(
const Maybe<IPCStream>& aStream) {
nsCOMPtr<nsIInputStream> stream = mozilla::ipc::DeserializeIPCStream(aStream);
RefPtr<RemoteLazyInputStream> pendingStream;
nsCOMPtr<nsIEventTarget> eventTarget;
{
MutexAutoLock lock(mMutex);
// We have been shutdown in the meantime.
if (mState == eInactive) {
return IPC_OK();
}
MOZ_ASSERT(!mPendingOperations.IsEmpty());
MOZ_ASSERT(mState == eActive);
pendingStream = mPendingOperations[0].mStream;
eventTarget = mPendingOperations[0].mEventTarget;
MOZ_ASSERT(mPendingOperations[0].mOp == PendingOperation::eStreamNeeded);
mPendingOperations.RemoveElementAt(0);
}
RefPtr<StreamReadyRunnable> runnable =
new StreamReadyRunnable(pendingStream, stream.forget());
// If RemoteLazyInputStream::AsyncWait() has been executed without passing an
// event target, we run the callback synchronous because any thread could be
// result to be the wrong one. See more in nsIAsyncInputStream::asyncWait
// documentation.
if (eventTarget) {
eventTarget->Dispatch(runnable, NS_DISPATCH_NORMAL);
} else {
runnable->Run();
}
return IPC_OK();
}
void RemoteLazyInputStreamChild::LengthNeeded(RemoteLazyInputStream* aStream,
nsIEventTarget* aEventTarget) {
MutexAutoLock lock(mMutex);
if (mState == eInactive) {
return;
}
MOZ_ASSERT(mStreams.Contains(aStream));
PendingOperation* opt = mPendingOperations.AppendElement();
opt->mStream = aStream;
opt->mEventTarget = aEventTarget;
opt->mOp = PendingOperation::eLengthNeeded;
if (mState == eActiveMigrating || mState == eInactiveMigrating) {
// This operation will be continued when the migration is completed.
return;
}
MOZ_ASSERT(mState == eActive);
if (mOwningEventTarget->IsOnCurrentThread()) {
SendLengthNeeded();
return;
}
RefPtr<LengthNeededRunnable> runnable = new LengthNeededRunnable(this);
mOwningEventTarget->Dispatch(runnable.forget(), NS_DISPATCH_NORMAL);
}
mozilla::ipc::IPCResult RemoteLazyInputStreamChild::RecvLengthReady(
const int64_t& aLength) {
RefPtr<RemoteLazyInputStream> pendingStream;
nsCOMPtr<nsIEventTarget> eventTarget;
{
MutexAutoLock lock(mMutex);
// We have been shutdown in the meantime.
if (mState == eInactive) {
return IPC_OK();
}
MOZ_ASSERT(!mPendingOperations.IsEmpty());
MOZ_ASSERT(mState == eActive);
pendingStream = mPendingOperations[0].mStream;
eventTarget = mPendingOperations[0].mEventTarget;
MOZ_ASSERT(mPendingOperations[0].mOp == PendingOperation::eLengthNeeded);
mPendingOperations.RemoveElementAt(0);
}
RefPtr<LengthReadyRunnable> runnable =
new LengthReadyRunnable(pendingStream, aLength);
MOZ_ASSERT(eventTarget);
eventTarget->Dispatch(runnable, NS_DISPATCH_NORMAL);
return IPC_OK();
}
void RemoteLazyInputStreamChild::Migrated() {
MutexAutoLock lock(mMutex);
MOZ_ASSERT(mState == eInactiveMigrating);
mWorkerRef = nullptr;
mOwningEventTarget = GetCurrentSerialEventTarget();
MOZ_ASSERT(
RemoteLazyInputStreamThread::IsOnFileEventTarget(mOwningEventTarget));
// Maybe we have no reasons to keep this actor alive.
if (mStreams.IsEmpty()) {
mState = eInactive;
SendClose();
return;
}
mState = eActive;
// Let's processing the pending operations. We need a stream for each pending
// operation.
for (uint32_t i = 0; i < mPendingOperations.Length(); ++i) {
if (mPendingOperations[i].mOp == PendingOperation::eStreamNeeded) {
SendStreamNeeded();
} else {
MOZ_ASSERT(mPendingOperations[i].mOp == PendingOperation::eLengthNeeded);
SendLengthNeeded();
}
void RemoteLazyInputStreamChild::ActorDestroy(ActorDestroyReason aReason) {
if (mStreamCount != 0) {
NS_WARNING(
nsPrintfCString("RemoteLazyInputStreamChild disconnected unexpectedly "
"(%zu streams remaining)! %p %s",
size_t(mStreamCount), this, nsIDToCString(mID).get())
.get());
}
}

View File

@ -8,97 +8,32 @@
#define mozilla_RemoteLazyInputStreamChild_h
#include "mozilla/PRemoteLazyInputStreamChild.h"
#include "mozilla/RemoteLazyInputStream.h"
#include "mozilla/Mutex.h"
#include "mozilla/UniquePtr.h"
#include "nsTArray.h"
namespace mozilla {
class RemoteLazyInputStream;
namespace dom {
class ThreadSafeWorkerRef;
}
class RemoteLazyInputStreamChild final : public PRemoteLazyInputStreamChild {
public:
enum ActorState {
// The actor is connected via IPDL to the parent.
eActive,
// The actor is disconnected.
eInactive,
// The actor is waiting to be disconnected. Once it has been disconnected,
// it will be reactivated on the DOM-File thread.
eActiveMigrating,
// The actor has been disconnected and it's waiting to be connected on the
// DOM-File thread.
eInactiveMigrating,
};
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RemoteLazyInputStreamChild, final)
RemoteLazyInputStreamChild(const nsID& aID, uint64_t aSize);
explicit RemoteLazyInputStreamChild(const nsID& aID);
void ActorDestroy(IProtocol::ActorDestroyReason aReason) override;
const nsID& StreamID() const { return mID; }
ActorState State();
// Manage the count of streams registered on this actor. When the count
// reaches 0 the connection to our remote process will be closed.
void StreamCreated();
void StreamConsumed();
already_AddRefed<RemoteLazyInputStream> CreateStream();
void ForgetStream(RemoteLazyInputStream* aStream);
const nsID& ID() const { return mID; }
uint64_t Size() const { return mSize; }
void StreamNeeded(RemoteLazyInputStream* aStream,
nsIEventTarget* aEventTarget);
mozilla::ipc::IPCResult RecvStreamReady(const Maybe<IPCStream>& aStream);
void LengthNeeded(RemoteLazyInputStream* aStream,
nsIEventTarget* aEventTarget);
mozilla::ipc::IPCResult RecvLengthReady(const int64_t& aLength);
void Shutdown();
void Migrated();
void ActorDestroy(ActorDestroyReason aReason) override;
private:
~RemoteLazyInputStreamChild() override;
// Raw pointers because these streams keep this actor alive. When the last
// stream is unregister, the actor will be deleted. This list is protected by
// mutex.
nsTArray<RemoteLazyInputStream*> mStreams;
// This mutex protects mStreams because that can be touched in any thread.
Mutex mMutex MOZ_UNANNOTATED;
const nsID mID;
const uint64_t mSize;
ActorState mState;
// This struct and the array are used for creating streams when needed.
struct PendingOperation {
RefPtr<RemoteLazyInputStream> mStream;
nsCOMPtr<nsIEventTarget> mEventTarget;
enum {
eStreamNeeded,
eLengthNeeded,
} mOp;
};
nsTArray<PendingOperation> mPendingOperations;
nsCOMPtr<nsISerialEventTarget> mOwningEventTarget;
RefPtr<dom::ThreadSafeWorkerRef> mWorkerRef;
std::atomic<size_t> mStreamCount{0};
};
} // namespace mozilla

View File

@ -5,257 +5,144 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "RemoteLazyInputStreamParent.h"
#include "mozilla/ipc/IPCStreamUtils.h"
#include "mozilla/InputStreamLengthHelper.h"
#include "RemoteLazyInputStreamStorage.h"
#include "mozilla/InputStreamLengthHelper.h"
#include "mozilla/ipc/Endpoint.h"
#include "mozilla/ipc/IPCStreamUtils.h"
#include "mozilla/ipc/InputStreamParams.h"
#include "mozilla/ipc/ProtocolUtils.h"
#include "nsStreamUtils.h"
#include "nsServiceManagerUtils.h"
#include "nsNetCID.h"
namespace mozilla {
template <typename M>
/* static */
already_AddRefed<RemoteLazyInputStreamParent>
RemoteLazyInputStreamParent::CreateCommon(nsIInputStream* aInputStream,
uint64_t aSize, uint64_t aChildID,
nsresult* aRv, M* aManager) {
MOZ_ASSERT(aInputStream);
MOZ_ASSERT(aRv);
nsID id;
*aRv = nsID::GenerateUUIDInPlace(id);
if (NS_WARN_IF(NS_FAILED(*aRv))) {
return nullptr;
}
auto storageOrErr = RemoteLazyInputStreamStorage::Get();
if (NS_WARN_IF(storageOrErr.isErr())) {
*aRv = storageOrErr.unwrapErr();
return nullptr;
}
auto storage = storageOrErr.unwrap();
storage->AddStream(aInputStream, id, aSize, aChildID);
RefPtr<RemoteLazyInputStreamParent> parent =
new RemoteLazyInputStreamParent(id, aSize, aManager);
return parent.forget();
}
/* static */
already_AddRefed<RemoteLazyInputStreamParent>
RemoteLazyInputStreamParent::Create(const nsID& aID, uint64_t aSize,
PBackgroundParent* aManager) {
RefPtr<RemoteLazyInputStreamParent> actor =
new RemoteLazyInputStreamParent(aID, aSize, aManager);
extern mozilla::LazyLogModule gRemoteLazyStreamLog;
RemoteLazyInputStreamParent::RemoteLazyInputStreamParent(const nsID& aID)
: mID(aID) {
auto storage = RemoteLazyInputStreamStorage::Get().unwrapOr(nullptr);
if (storage) {
actor->mCallback = storage->TakeCallback(aID);
return actor.forget();
storage->ActorCreated(mID);
}
return nullptr;
}
/* static */
already_AddRefed<RemoteLazyInputStreamParent>
RemoteLazyInputStreamParent::Create(nsIInputStream* aInputStream,
uint64_t aSize, uint64_t aChildID,
nsresult* aRv,
mozilla::ipc::PBackgroundParent* aManager) {
return CreateCommon(aInputStream, aSize, aChildID, aRv, aManager);
}
/* static */
already_AddRefed<RemoteLazyInputStreamParent>
RemoteLazyInputStreamParent::Create(const nsID& aID, uint64_t aSize,
net::SocketProcessParent* aManager) {
RefPtr<RemoteLazyInputStreamParent> actor =
new RemoteLazyInputStreamParent(aID, aSize, aManager);
auto storage = RemoteLazyInputStreamStorage::Get().unwrapOr(nullptr);
if (storage) {
actor->mCallback = storage->TakeCallback(aID);
return actor.forget();
}
return nullptr;
}
/* static */
already_AddRefed<RemoteLazyInputStreamParent>
RemoteLazyInputStreamParent::Create(
nsIInputStream* aInputStream, uint64_t aSize, uint64_t aChildID,
nsresult* aRv, mozilla::net::SocketProcessParent* aManager) {
return CreateCommon(aInputStream, aSize, aChildID, aRv, aManager);
}
template already_AddRefed<RemoteLazyInputStreamParent>
RemoteLazyInputStreamParent::CreateCommon<mozilla::net::SocketProcessParent>(
nsIInputStream*, uint64_t, uint64_t, nsresult*,
mozilla::net::SocketProcessParent*);
/* static */
already_AddRefed<RemoteLazyInputStreamParent>
RemoteLazyInputStreamParent::Create(nsIInputStream* aInputStream,
uint64_t aSize, uint64_t aChildID,
nsresult* aRv,
mozilla::dom::ContentParent* aManager) {
return CreateCommon(aInputStream, aSize, aChildID, aRv, aManager);
}
RemoteLazyInputStreamParent::RemoteLazyInputStreamParent(
const nsID& aID, uint64_t aSize, dom::ContentParent* aManager)
: mID(aID),
mSize(aSize),
mContentManager(aManager),
mPBackgroundManager(nullptr),
mSocketProcessManager(nullptr),
mMigrating(false) {}
RemoteLazyInputStreamParent::RemoteLazyInputStreamParent(
const nsID& aID, uint64_t aSize, PBackgroundParent* aManager)
: mID(aID),
mSize(aSize),
mContentManager(nullptr),
mPBackgroundManager(aManager),
mSocketProcessManager(nullptr),
mMigrating(false) {}
RemoteLazyInputStreamParent::RemoteLazyInputStreamParent(
const nsID& aID, uint64_t aSize, net::SocketProcessParent* aManager)
: mID(aID),
mSize(aSize),
mContentManager(nullptr),
mPBackgroundManager(nullptr),
mSocketProcessManager(aManager),
mMigrating(false) {}
void RemoteLazyInputStreamParent::ActorDestroy(
IProtocol::ActorDestroyReason aReason) {
MOZ_ASSERT(mContentManager || mPBackgroundManager || mSocketProcessManager);
mContentManager = nullptr;
mPBackgroundManager = nullptr;
mSocketProcessManager = nullptr;
RefPtr<RemoteLazyInputStreamParentCallback> callback;
mCallback.swap(callback);
auto storage = RemoteLazyInputStreamStorage::Get().unwrapOr(nullptr);
if (mMigrating) {
if (callback && storage) {
// We need to assign this callback to the next parent.
storage->StoreCallback(mID, callback);
}
return;
}
if (storage) {
storage->ForgetStream(mID);
}
if (callback) {
callback->ActorDestroyed(mID);
storage->ActorDestroyed(mID);
}
}
void RemoteLazyInputStreamParent::SetCallback(
RemoteLazyInputStreamParentCallback* aCallback) {
MOZ_ASSERT(aCallback);
MOZ_ASSERT(!mCallback);
mCallback = aCallback;
}
mozilla::ipc::IPCResult RemoteLazyInputStreamParent::RecvStreamNeeded() {
MOZ_ASSERT(mContentManager || mPBackgroundManager || mSocketProcessManager);
nsCOMPtr<nsIInputStream> stream;
auto storage = RemoteLazyInputStreamStorage::Get().unwrapOr(nullptr);
if (storage) {
storage->GetStream(mID, 0, mSize, getter_AddRefs(stream));
mozilla::ipc::IPCResult RemoteLazyInputStreamParent::RecvClone(
mozilla::ipc::Endpoint<PRemoteLazyInputStreamParent>&& aCloneEndpoint) {
if (!aCloneEndpoint.IsValid()) {
return IPC_FAIL(this, "Unexpected invalid endpoint in RecvClone");
}
if (!stream) {
if (!SendStreamReady(Nothing())) {
return IPC_FAIL(this, "SendStreamReady failed");
}
MOZ_LOG(gRemoteLazyStreamLog, LogLevel::Debug,
("Parent::RecvClone %s", nsIDToCString(mID).get()));
return IPC_OK();
}
mozilla::ipc::AutoIPCStream ipcStream;
bool ok = false;
if (mContentManager) {
MOZ_ASSERT(NS_IsMainThread());
ok = ipcStream.Serialize(stream, mContentManager);
} else if (mPBackgroundManager) {
ok = ipcStream.Serialize(stream, mPBackgroundManager);
} else {
MOZ_ASSERT(mSocketProcessManager);
ok = ipcStream.Serialize(stream, mSocketProcessManager);
}
if (NS_WARN_IF(!ok)) {
return IPC_FAIL(this, "SendStreamReady failed");
}
if (!SendStreamReady(Some(ipcStream.TakeValue()))) {
return IPC_FAIL(this, "SendStreamReady failed");
}
auto* newActor = new RemoteLazyInputStreamParent(mID);
aCloneEndpoint.Bind(newActor);
return IPC_OK();
}
mozilla::ipc::IPCResult RemoteLazyInputStreamParent::RecvLengthNeeded() {
MOZ_ASSERT(mContentManager || mPBackgroundManager || mSocketProcessManager);
mozilla::ipc::IPCResult RemoteLazyInputStreamParent::RecvStreamNeeded(
uint64_t aStart, uint64_t aLength, StreamNeededResolver&& aResolver) {
nsCOMPtr<nsIInputStream> stream;
auto storage = RemoteLazyInputStreamStorage::Get().unwrapOr(nullptr);
if (storage) {
storage->GetStream(mID, 0, mSize, getter_AddRefs(stream));
storage->GetStream(mID, aStart, aLength, getter_AddRefs(stream));
}
if (!stream) {
if (!SendLengthReady(-1)) {
return IPC_FAIL(this, "SendLengthReady failed");
MOZ_LOG(gRemoteLazyStreamLog, LogLevel::Warning,
("Parent::RecvStreamNeeded not available! %s",
nsIDToCString(mID).get()));
aResolver(Nothing());
return IPC_OK();
}
// XXX: This should be much cleaner once the API for serializing IPCStream has
// been simplified.
ipc::InputStreamParams params;
if (nsCOMPtr<nsIIPCSerializableInputStream> serializable =
do_QueryInterface(stream)) {
nsTArray<FileDescriptor> unused;
uint32_t sizeUsed = 0;
serializable->Serialize(
params, unused, false, 128 * 1024, &sizeUsed,
(mozilla::ipc::ParentToChildStreamActorManager*)nullptr);
MOZ_ASSERT(unused.IsEmpty());
} else {
RefPtr<ipc::DataPipeSender> sender;
RefPtr<ipc::DataPipeReceiver> receiver;
nsresult rv = NewDataPipe(ipc::kDefaultDataPipeCapacity,
getter_AddRefs(sender), getter_AddRefs(receiver));
if (NS_WARN_IF(NS_FAILED(rv))) {
return IPC_FAIL(this, "NewDataPipe failed");
}
nsCOMPtr<nsIEventTarget> target =
do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
rv = NS_AsyncCopy(stream, sender, target, NS_ASYNCCOPY_VIA_WRITESEGMENTS,
ipc::kDefaultDataPipeCapacity, nullptr, nullptr);
if (NS_WARN_IF(NS_FAILED(rv))) {
return IPC_FAIL(this, "NS_AsyncCopy failed");
}
params = ipc::DataPipeReceiverStreamParams(receiver);
}
MOZ_LOG(gRemoteLazyStreamLog, LogLevel::Verbose,
("Parent::RecvStreamNeeded resolve %s", nsIDToCString(mID).get()));
aResolver(Some(IPCStream(params)));
return IPC_OK();
}
mozilla::ipc::IPCResult RemoteLazyInputStreamParent::RecvLengthNeeded(
LengthNeededResolver&& aResolver) {
nsCOMPtr<nsIInputStream> stream;
auto storage = RemoteLazyInputStreamStorage::Get().unwrapOr(nullptr);
if (storage) {
storage->GetStream(mID, 0, UINT64_MAX, getter_AddRefs(stream));
}
if (!stream) {
MOZ_LOG(gRemoteLazyStreamLog, LogLevel::Warning,
("Parent::RecvLengthNeeded not available! %s",
nsIDToCString(mID).get()));
aResolver(-1);
return IPC_OK();
}
int64_t length = -1;
if (InputStreamLengthHelper::GetSyncLength(stream, &length)) {
Unused << SendLengthReady(length);
MOZ_LOG(gRemoteLazyStreamLog, LogLevel::Verbose,
("Parent::RecvLengthNeeded sync resolve %" PRId64 "! %s", length,
nsIDToCString(mID).get()));
aResolver(length);
return IPC_OK();
}
RefPtr<RemoteLazyInputStreamParent> self = this;
InputStreamLengthHelper::GetAsyncLength(stream, [self](int64_t aLength) {
if (self->mContentManager || self->mPBackgroundManager ||
self->mSocketProcessManager) {
Unused << self->SendLengthReady(aLength);
}
});
InputStreamLengthHelper::GetAsyncLength(
stream, [aResolver, id = mID](int64_t aLength) {
MOZ_LOG(gRemoteLazyStreamLog, LogLevel::Verbose,
("Parent::RecvLengthNeeded async resolve %" PRId64 "! %s",
aLength, nsIDToCString(id).get()));
aResolver(aLength);
});
return IPC_OK();
}
mozilla::ipc::IPCResult RemoteLazyInputStreamParent::RecvClose() {
MOZ_ASSERT(mContentManager || mPBackgroundManager || mSocketProcessManager);
Unused << Send__delete__(this);
return IPC_OK();
}
mozilla::ipc::IPCResult RemoteLazyInputStreamParent::Recv__delete__() {
MOZ_ASSERT(mContentManager || mPBackgroundManager || mSocketProcessManager);
mMigrating = true;
mozilla::ipc::IPCResult RemoteLazyInputStreamParent::RecvGoodbye() {
MOZ_LOG(gRemoteLazyStreamLog, LogLevel::Verbose,
("Parent::RecvGoodbye! %s", nsIDToCString(mID).get()));
Close();
return IPC_OK();
}

View File

@ -13,96 +13,30 @@ class nsIInputStream;
namespace mozilla {
namespace dom {
class ContentParent;
}
namespace net {
class SocketProcessParent;
}
class NS_NO_VTABLE RemoteLazyInputStreamParentCallback {
public:
virtual void ActorDestroyed(const nsID& aID) = 0;
NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING
protected:
virtual ~RemoteLazyInputStreamParentCallback() = default;
};
class RemoteLazyInputStreamParent final : public PRemoteLazyInputStreamParent {
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RemoteLazyInputStreamParent, final)
// The size of the inputStream must be passed as argument in order to avoid
// the use of nsIInputStream::Available() which could open a fileDescriptor in
// case the stream is a nsFileStream.
static already_AddRefed<RemoteLazyInputStreamParent> Create(
nsIInputStream* aInputStream, uint64_t aSize, uint64_t aChildID,
nsresult* aRv, mozilla::dom::ContentParent* aManager);
static already_AddRefed<RemoteLazyInputStreamParent> Create(
nsIInputStream* aInputStream, uint64_t aSize, uint64_t aChildID,
nsresult* aRv, mozilla::ipc::PBackgroundParent* aManager);
static already_AddRefed<RemoteLazyInputStreamParent> Create(
nsIInputStream* aInputStream, uint64_t aSize, uint64_t aChildID,
nsresult* aRv, mozilla::net::SocketProcessParent* aManager);
static already_AddRefed<RemoteLazyInputStreamParent> Create(
const nsID& aID, uint64_t aSize,
mozilla::ipc::PBackgroundParent* aManager);
static already_AddRefed<RemoteLazyInputStreamParent> Create(
const nsID& aID, uint64_t aSize,
mozilla::net::SocketProcessParent* aManager);
void ActorDestroy(IProtocol::ActorDestroyReason aReason) override;
explicit RemoteLazyInputStreamParent(const nsID& aID);
const nsID& ID() const { return mID; }
uint64_t Size() const { return mSize; }
mozilla::ipc::IPCResult RecvClone(
mozilla::ipc::Endpoint<PRemoteLazyInputStreamParent>&& aCloneEndpoint);
void SetCallback(RemoteLazyInputStreamParentCallback* aCallback);
mozilla::ipc::IPCResult RecvStreamNeeded(uint64_t aStart, uint64_t aLength,
StreamNeededResolver&& aResolver);
mozilla::ipc::IPCResult RecvStreamNeeded();
mozilla::ipc::IPCResult RecvLengthNeeded(LengthNeededResolver&& aResolver);
mozilla::ipc::IPCResult RecvLengthNeeded();
mozilla::ipc::IPCResult RecvGoodbye();
mozilla::ipc::IPCResult RecvClose();
mozilla::ipc::IPCResult Recv__delete__() override;
void ActorDestroy(IProtocol::ActorDestroyReason aReason) override;
private:
template <typename M>
static already_AddRefed<RemoteLazyInputStreamParent> CreateCommon(
nsIInputStream* aInputStream, uint64_t aSize, uint64_t aChildID,
nsresult* aRv, M* aManager);
RemoteLazyInputStreamParent(const nsID& aID, uint64_t aSize,
mozilla::dom::ContentParent* aManager);
RemoteLazyInputStreamParent(const nsID& aID, uint64_t aSize,
mozilla::ipc::PBackgroundParent* aManager);
RemoteLazyInputStreamParent(const nsID& aID, uint64_t aSize,
mozilla::net::SocketProcessParent* aManager);
~RemoteLazyInputStreamParent() override = default;
const nsID mID;
const uint64_t mSize;
// Only 1 of these is set. Raw pointer because these managers are keeping
// the parent actor alive. The pointers will be nullified in ActorDestroyed.
mozilla::dom::ContentParent* mContentManager;
mozilla::ipc::PBackgroundParent* mPBackgroundManager;
mozilla::net::SocketProcessParent* mSocketProcessManager;
RefPtr<RemoteLazyInputStreamParentCallback> mCallback;
bool mMigrating;
};
} // namespace mozilla

View File

@ -17,6 +17,8 @@ namespace mozilla {
using namespace hal;
extern mozilla::LazyLogModule gRemoteLazyStreamLog;
namespace {
StaticMutex gMutex;
StaticRefPtr<RemoteLazyInputStreamStorage> gStorage;
@ -49,61 +51,40 @@ void RemoteLazyInputStreamStorage::Initialize() {
gStorage = new RemoteLazyInputStreamStorage();
MOZ_ALWAYS_SUCCEEDS(NS_CreateBackgroundTaskQueue(
"RemoteLazyInputStreamStorage", getter_AddRefs(gStorage->mTaskQueue)));
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
if (obs) {
obs->AddObserver(gStorage, "xpcom-shutdown", false);
obs->AddObserver(gStorage, "ipc:content-shutdown", false);
}
}
NS_IMETHODIMP
RemoteLazyInputStreamStorage::Observe(nsISupports* aSubject, const char* aTopic,
const char16_t* aData) {
if (!strcmp(aTopic, "xpcom-shutdown")) {
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
if (obs) {
obs->RemoveObserver(this, "xpcom-shutdown");
obs->RemoveObserver(this, "ipc:content-shutdown");
}
MOZ_ASSERT(!strcmp(aTopic, "xpcom-shutdown"));
mozilla::StaticMutexAutoLock lock(gMutex);
gStorage = nullptr;
return NS_OK;
}
MOZ_ASSERT(!strcmp(aTopic, "ipc:content-shutdown"));
nsCOMPtr<nsIPropertyBag2> props = do_QueryInterface(aSubject);
if (NS_WARN_IF(!props)) {
return NS_ERROR_FAILURE;
}
uint64_t childID = CONTENT_PROCESS_ID_UNKNOWN;
props->GetPropertyAsUint64(u"childID"_ns, &childID);
if (NS_WARN_IF(childID == CONTENT_PROCESS_ID_UNKNOWN)) {
return NS_ERROR_FAILURE;
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
if (obs) {
obs->RemoveObserver(this, "xpcom-shutdown");
}
mozilla::StaticMutexAutoLock lock(gMutex);
for (auto iter = mStorage.Iter(); !iter.Done(); iter.Next()) {
if (iter.Data()->mChildID == childID) {
iter.Remove();
}
}
gStorage = nullptr;
return NS_OK;
}
void RemoteLazyInputStreamStorage::AddStream(nsIInputStream* aInputStream,
const nsID& aID, uint64_t aSize,
uint64_t aChildID) {
const nsID& aID) {
MOZ_ASSERT(aInputStream);
MOZ_LOG(
gRemoteLazyStreamLog, LogLevel::Verbose,
("Storage::AddStream(%s) = %p", nsIDToCString(aID).get(), aInputStream));
UniquePtr<StreamData> data = MakeUnique<StreamData>();
data->mInputStream = aInputStream;
data->mChildID = aChildID;
data->mSize = aSize;
mozilla::StaticMutexAutoLock lock(gMutex);
mStorage.InsertOrUpdate(aID, std::move(data));
@ -111,6 +92,9 @@ void RemoteLazyInputStreamStorage::AddStream(nsIInputStream* aInputStream,
nsCOMPtr<nsIInputStream> RemoteLazyInputStreamStorage::ForgetStream(
const nsID& aID) {
MOZ_LOG(gRemoteLazyStreamLog, LogLevel::Verbose,
("Storage::ForgetStream(%s)", nsIDToCString(aID).get()));
UniquePtr<StreamData> entry;
mozilla::StaticMutexAutoLock lock(gMutex);
@ -134,8 +118,11 @@ void RemoteLazyInputStreamStorage::GetStream(const nsID& aID, uint64_t aStart,
nsIInputStream** aInputStream) {
*aInputStream = nullptr;
MOZ_LOG(gRemoteLazyStreamLog, LogLevel::Verbose,
("Storage::GetStream(%s, %" PRIu64 " %" PRIu64 ")",
nsIDToCString(aID).get(), aStart, aLength));
nsCOMPtr<nsIInputStream> inputStream;
uint64_t size;
// NS_CloneInputStream cannot be called when the mutex is locked because it
// can, recursively call GetStream() in case the child actor lives on the
@ -148,7 +135,6 @@ void RemoteLazyInputStreamStorage::GetStream(const nsID& aID, uint64_t aStart,
}
inputStream = data->mInputStream;
size = data->mSize;
}
MOZ_ASSERT(inputStream);
@ -177,7 +163,7 @@ void RemoteLazyInputStreamStorage::GetStream(const nsID& aID, uint64_t aStart,
}
// Now it's the right time to apply a slice if needed.
if (aStart > 0 || aLength < size) {
if (aStart > 0 || aLength < UINT64_MAX) {
clonedStream =
new SlicedInputStream(clonedStream.forget(), aStart, aLength);
}
@ -189,6 +175,10 @@ void RemoteLazyInputStreamStorage::StoreCallback(
const nsID& aID, RemoteLazyInputStreamParentCallback* aCallback) {
MOZ_ASSERT(aCallback);
MOZ_LOG(
gRemoteLazyStreamLog, LogLevel::Verbose,
("Storage::StoreCallback(%s, %p)", nsIDToCString(aID).get(), aCallback));
mozilla::StaticMutexAutoLock lock(gMutex);
StreamData* data = mStorage.Get(aID);
if (data) {
@ -199,6 +189,9 @@ void RemoteLazyInputStreamStorage::StoreCallback(
already_AddRefed<RemoteLazyInputStreamParentCallback>
RemoteLazyInputStreamStorage::TakeCallback(const nsID& aID) {
MOZ_LOG(gRemoteLazyStreamLog, LogLevel::Verbose,
("Storage::TakeCallback(%s)", nsIDToCString(aID).get()));
mozilla::StaticMutexAutoLock lock(gMutex);
StreamData* data = mStorage.Get(aID);
if (!data) {
@ -210,4 +203,41 @@ RemoteLazyInputStreamStorage::TakeCallback(const nsID& aID) {
return callback.forget();
}
void RemoteLazyInputStreamStorage::ActorCreated(const nsID& aID) {
mozilla::StaticMutexAutoLock lock(gMutex);
StreamData* data = mStorage.Get(aID);
if (!data) {
return;
}
size_t count = ++data->mActorCount;
MOZ_LOG(gRemoteLazyStreamLog, LogLevel::Verbose,
("Storage::ActorCreated(%s) = %zu", nsIDToCString(aID).get(), count));
}
void RemoteLazyInputStreamStorage::ActorDestroyed(const nsID& aID) {
UniquePtr<StreamData> entry;
{
mozilla::StaticMutexAutoLock lock(gMutex);
StreamData* data = mStorage.Get(aID);
if (!data) {
return;
}
auto newCount = --data->mActorCount;
MOZ_LOG(gRemoteLazyStreamLog, LogLevel::Verbose,
("Storage::ActorDestroyed(%s) = %zu (cb=%p)",
nsIDToCString(aID).get(), newCount, data->mCallback.get()));
if (newCount == 0) {
mStorage.Remove(aID, &entry);
}
}
if (entry && entry->mCallback) {
entry->mCallback->ActorDestroyed(aID);
}
}
} // namespace mozilla

View File

@ -16,7 +16,15 @@ struct nsID;
namespace mozilla {
class RemoteLazyInputStreamParentCallback;
class NS_NO_VTABLE RemoteLazyInputStreamParentCallback {
public:
virtual void ActorDestroyed(const nsID& aID) = 0;
NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING
protected:
virtual ~RemoteLazyInputStreamParentCallback() = default;
};
class RemoteLazyInputStreamStorage final : public nsIObserver {
public:
@ -28,8 +36,9 @@ class RemoteLazyInputStreamStorage final : public nsIObserver {
static Result<RefPtr<RemoteLazyInputStreamStorage>, nsresult> Get();
void AddStream(nsIInputStream* aInputStream, const nsID& aID, uint64_t aSize,
uint64_t aChildID);
nsISerialEventTarget* TaskQueue() { return mTaskQueue; }
void AddStream(nsIInputStream* aInputStream, const nsID& aID);
// Removes and returns the stream corresponding to the nsID. May return a
// nullptr if there's no stream stored for the nsID.
@ -46,19 +55,19 @@ class RemoteLazyInputStreamStorage final : public nsIObserver {
already_AddRefed<RemoteLazyInputStreamParentCallback> TakeCallback(
const nsID& aID);
void ActorCreated(const nsID& aID);
void ActorDestroyed(const nsID& aID);
private:
RemoteLazyInputStreamStorage() = default;
~RemoteLazyInputStreamStorage() = default;
nsCOMPtr<nsISerialEventTarget> mTaskQueue;
struct StreamData {
nsCOMPtr<nsIInputStream> mInputStream;
RefPtr<RemoteLazyInputStreamParentCallback> mCallback;
// This is the Process ID connected with this inputStream. We need to store
// this information in order to delete it if the child crashes/shutdowns.
uint64_t mChildID;
uint64_t mSize;
size_t mActorCount = 0;
};
nsClassHashtable<nsIDHashKey, StreamData> mStorage;

View File

@ -38,58 +38,10 @@ class ThreadInitializeRunnable final : public Runnable {
}
};
class MigrateActorRunnable final : public Runnable {
public:
explicit MigrateActorRunnable(RemoteLazyInputStreamChild* aActor)
: Runnable("dom::MigrateActorRunnable"), mActor(aActor) {
MOZ_ASSERT(mActor);
}
NS_IMETHOD
Run() override {
MOZ_ASSERT(mActor->State() ==
RemoteLazyInputStreamChild::eInactiveMigrating);
PBackgroundChild* actorChild =
BackgroundChild::GetOrCreateForCurrentThread();
if (!actorChild) {
return NS_OK;
}
if (actorChild->SendPRemoteLazyInputStreamConstructor(mActor, mActor->ID(),
mActor->Size())) {
mActor->Migrated();
}
return NS_OK;
}
private:
~MigrateActorRunnable() = default;
RefPtr<RemoteLazyInputStreamChild> mActor;
};
} // namespace
NS_IMPL_ISUPPORTS(RemoteLazyInputStreamThread, nsIObserver, nsIEventTarget)
/* static */
bool RemoteLazyInputStreamThread::IsOnFileEventTarget(
nsIEventTarget* aEventTarget) {
MOZ_ASSERT(aEventTarget);
// Note that we don't migrate actors when we are on the socket process
// because, on that process, we don't have complex life-time contexts such
// as workers and documents.
if (XRE_IsSocketProcess()) {
return true;
}
StaticMutexAutoLock lock(gRemoteLazyThreadMutex);
return gRemoteLazyThread && aEventTarget == gRemoteLazyThread->mThread;
}
/* static */
RemoteLazyInputStreamThread* RemoteLazyInputStreamThread::Get() {
StaticMutexAutoLock lock(gRemoteLazyThreadMutex);
@ -128,14 +80,6 @@ bool RemoteLazyInputStreamThread::Initialize() {
mThread = thread;
if (!mPendingActors.IsEmpty()) {
for (uint32_t i = 0; i < mPendingActors.Length(); ++i) {
MigrateActorInternal(mPendingActors[i]);
}
mPendingActors.Clear();
}
if (!NS_IsMainThread()) {
RefPtr<Runnable> runnable = new ThreadInitializeRunnable();
SchedulerGroup::Dispatch(TaskCategory::Other, runnable.forget());
@ -179,31 +123,6 @@ RemoteLazyInputStreamThread::Observe(nsISupports* aSubject, const char* aTopic,
return NS_OK;
}
void RemoteLazyInputStreamThread::MigrateActor(
RemoteLazyInputStreamChild* aActor) {
MOZ_ASSERT(aActor->State() == RemoteLazyInputStreamChild::eInactiveMigrating);
StaticMutexAutoLock lock(gRemoteLazyThreadMutex);
if (gShutdownHasStarted) {
return;
}
if (!mThread) {
// The thread is not initialized yet.
mPendingActors.AppendElement(aActor);
return;
}
MigrateActorInternal(aActor);
}
void RemoteLazyInputStreamThread::MigrateActorInternal(
RemoteLazyInputStreamChild* aActor) {
RefPtr<Runnable> runnable = new MigrateActorRunnable(aActor);
mThread->Dispatch(runnable, NS_DISPATCH_NORMAL);
}
// nsIEventTarget
NS_IMETHODIMP_(bool)

View File

@ -25,14 +25,10 @@ class RemoteLazyInputStreamThread final : public nsIObserver,
NS_DECL_NSIOBSERVER
NS_DECL_NSIEVENTTARGET
static bool IsOnFileEventTarget(nsIEventTarget* aEventTarget);
static RemoteLazyInputStreamThread* Get();
static RemoteLazyInputStreamThread* GetOrCreate();
void MigrateActor(RemoteLazyInputStreamChild* aActor);
bool Initialize();
void InitializeOnMainThread();
@ -40,13 +36,7 @@ class RemoteLazyInputStreamThread final : public nsIObserver,
private:
~RemoteLazyInputStreamThread() = default;
void MigrateActorInternal(RemoteLazyInputStreamChild* aActor);
nsCOMPtr<nsIThread> mThread;
// This is populated if MigrateActor() is called before the initialization of
// the thread.
nsTArray<RefPtr<RemoteLazyInputStreamChild>> mPendingActors;
};
bool IsOnDOMFileThread();

View File

@ -1,119 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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 "RemoteLazyInputStreamUtils.h"
#include "RemoteLazyInputStream.h"
#include "RemoteLazyInputStreamChild.h"
#include "RemoteLazyInputStreamParent.h"
#include "mozilla/ipc/BackgroundParent.h"
#include "mozilla/ipc/PBackgroundParent.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/ipc/IPCStreamUtils.h"
#include "RemoteLazyInputStreamStorage.h"
#include "StreamBlobImpl.h"
namespace mozilla {
namespace {
template <typename M>
nsresult SerializeInputStreamParent(nsIInputStream* aInputStream,
uint64_t aSize, uint64_t aChildID,
PRemoteLazyInputStreamParent*& aActorParent,
M* aManager) {
// Parent to Child we always send a RemoteLazyInputStream.
MOZ_ASSERT(XRE_IsParentProcess());
nsCOMPtr<nsIInputStream> stream = aInputStream;
// In case this is a RemoteLazyInputStream, we don't want to create a loop:
// RemoteLazyInputStreamParent -> RemoteLazyInputStream ->
// RemoteLazyInputStreamParent. Let's use the underlying inputStream instead.
nsCOMPtr<mozIRemoteLazyInputStream> remoteLazyInputStream =
do_QueryInterface(aInputStream);
if (remoteLazyInputStream) {
stream = remoteLazyInputStream->GetInternalStream();
// If we don't have an underlying stream, it's better to terminate here
// instead of sending an 'empty' RemoteLazyInputStream actor on the other
// side, unable to be used.
if (NS_WARN_IF(!stream)) {
return NS_ERROR_FAILURE;
}
}
nsresult rv;
RefPtr<RemoteLazyInputStreamParent> parentActor =
RemoteLazyInputStreamParent::Create(stream, aSize, aChildID, &rv,
aManager);
if (!parentActor) {
return rv;
}
if (!aManager->SendPRemoteLazyInputStreamConstructor(
parentActor, parentActor->ID(), parentActor->Size())) {
return NS_ERROR_FAILURE;
}
aActorParent = parentActor;
return NS_OK;
}
} // anonymous namespace
// static
nsresult RemoteLazyInputStreamUtils::SerializeInputStream(
nsIInputStream* aInputStream, uint64_t aSize, RemoteLazyStream& aOutStream,
dom::ContentParent* aManager) {
PRemoteLazyInputStreamParent* actor = nullptr;
nsresult rv = SerializeInputStreamParent(
aInputStream, aSize, aManager->ChildID(), actor, aManager);
NS_ENSURE_SUCCESS(rv, rv);
aOutStream = actor;
return NS_OK;
}
// static
nsresult RemoteLazyInputStreamUtils::SerializeInputStream(
nsIInputStream* aInputStream, uint64_t aSize, RemoteLazyStream& aOutStream,
mozilla::ipc::PBackgroundParent* aManager) {
PRemoteLazyInputStreamParent* actor = nullptr;
nsresult rv = SerializeInputStreamParent(
aInputStream, aSize, mozilla::ipc::BackgroundParent::GetChildID(aManager),
actor, aManager);
NS_ENSURE_SUCCESS(rv, rv);
aOutStream = actor;
return NS_OK;
}
// static
nsresult RemoteLazyInputStreamUtils::SerializeInputStream(
nsIInputStream* aInputStream, uint64_t aSize, RemoteLazyStream& aOutStream,
dom::ContentChild* aManager) {
mozilla::ipc::AutoIPCStream ipcStream(true /* delayed start */);
if (!ipcStream.Serialize(aInputStream, aManager)) {
return NS_ERROR_FAILURE;
}
aOutStream = ipcStream.TakeValue();
return NS_OK;
}
// static
nsresult RemoteLazyInputStreamUtils::SerializeInputStream(
nsIInputStream* aInputStream, uint64_t aSize, RemoteLazyStream& aOutStream,
mozilla::ipc::PBackgroundChild* aManager) {
mozilla::ipc::AutoIPCStream ipcStream(true /* delayed start */);
if (!ipcStream.Serialize(aInputStream, aManager)) {
return NS_ERROR_FAILURE;
}
aOutStream = ipcStream.TakeValue();
return NS_OK;
}
} // namespace mozilla

View File

@ -1,59 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */
#ifndef mozilla_RemoteLazyInputStreamUtils_h
#define mozilla_RemoteLazyInputStreamUtils_h
#include <cstdint>
/*
* RemoteLazyInputStream was previously part of the IPCBlob world.
* See IPCBlobUtils.h to know how to use it. As a follow up, the documentation
* will be partially moved here too.
*/
class nsIInputStream;
enum class nsresult : uint32_t;
namespace mozilla {
class RemoteLazyStream;
namespace ipc {
class IPCStream;
class PBackgroundChild;
class PBackgroundParent;
} // namespace ipc
namespace dom {
class ContentChild;
class ContentParent;
} // namespace dom
class RemoteLazyInputStreamUtils final {
public:
static nsresult SerializeInputStream(nsIInputStream* aInputStream,
uint64_t aSize,
RemoteLazyStream& aOutStream,
dom::ContentParent* aManager);
static nsresult SerializeInputStream(
nsIInputStream* aInputStream, uint64_t aSize,
RemoteLazyStream& aOutStream, mozilla::ipc::PBackgroundParent* aManager);
static nsresult SerializeInputStream(nsIInputStream* aInputStream,
uint64_t aSize,
RemoteLazyStream& aOutStream,
dom::ContentChild* aManager);
static nsresult SerializeInputStream(
nsIInputStream* aInputStream, uint64_t aSize,
RemoteLazyStream& aOutStream, mozilla::ipc::PBackgroundChild* aManager);
};
} // namespace mozilla
#endif // mozilla_RemoteLazyInputStreamUtils_h

View File

@ -27,7 +27,6 @@ EXPORTS.mozilla += [
"RemoteLazyInputStreamParent.h",
"RemoteLazyInputStreamStorage.h",
"RemoteLazyInputStreamThread.h",
"RemoteLazyInputStreamUtils.h",
]
UNIFIED_SOURCES += [
@ -39,7 +38,6 @@ UNIFIED_SOURCES += [
"RemoteLazyInputStreamParent.cpp",
"RemoteLazyInputStreamStorage.cpp",
"RemoteLazyInputStreamThread.cpp",
"RemoteLazyInputStreamUtils.cpp",
"TemporaryIPCBlobChild.cpp",
"TemporaryIPCBlobParent.cpp",
]

View File

@ -13,5 +13,17 @@ interface nsIInputStream;
[scriptable, builtinclass, uuid(4125585f-b0c2-4964-a83c-4b0d99f26d49)]
interface mozIRemoteLazyInputStream : nsISupports
{
[notxpcom, noscript] nsIInputStream GetInternalStream();
/**
* Attempts to take the internal stream out of this mozIRemoteLazyInputStream.
* Throws NS_BASE_STREAM_WOULD_BLOCK if the stream isn't available yet, and
* NS_BASE_STREAM_CLOSED if it was already closed.
*/
[noscript] nsIInputStream TakeInternalStream();
/**
* If this RemoteLazyInputStream is actively backed by an actor, get the
* underlying actor's ID. Will throw if the underlying actor is no longer
* available.
*/
[noscript] readonly attribute nsIDRef internalStreamID;
};

View File

@ -4,7 +4,6 @@
include protocol PBackgroundFileRequest;
include protocol PBackgroundMutableFile;
include protocol PRemoteLazyInputStream; // FIXME: bug 792908
include IPCBlob;

View File

@ -5,7 +5,6 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
include protocol PBackground;
include protocol PRemoteLazyInputStream;
include IPCBlob;

View File

@ -2750,8 +2750,9 @@ nsresult BackgroundRequestChild::PreprocessHelper::ProcessStream() {
do_QueryInterface(mStream);
MOZ_ASSERT(blobInputStream);
nsCOMPtr<nsIInputStream> internalInputStream =
blobInputStream->GetInternalStream();
nsCOMPtr<nsIInputStream> internalInputStream;
MOZ_ALWAYS_SUCCEEDS(
blobInputStream->TakeInternalStream(getter_AddRefs(internalInputStream)));
MOZ_ASSERT(internalInputStream);
QM_TRY(MOZ_TO_RESULT(

View File

@ -78,6 +78,7 @@
#include "mozilla/RefCountType.h"
#include "mozilla/RefCounted.h"
#include "mozilla/RemoteLazyInputStreamParent.h"
#include "mozilla/RemoteLazyInputStreamStorage.h"
#include "mozilla/Result.h"
#include "mozilla/ResultExtensions.h"
#include "mozilla/SchedulerGroup.h"
@ -145,7 +146,6 @@
#include "mozilla/ipc/PBackgroundSharedTypes.h"
#include "mozilla/ipc/ProtocolUtils.h"
#include "mozilla/mozalloc.h"
#include "mozilla/PRemoteLazyInputStreamParent.h"
#include "mozilla/storage/Variant.h"
#include "nsBaseHashtable.h"
#include "nsCOMPtr.h"
@ -2490,21 +2490,24 @@ class Database::StartTransactionOp final
class Database::UnmapBlobCallback final
: public RemoteLazyInputStreamParentCallback {
SafeRefPtr<Database> mDatabase;
nsCOMPtr<nsISerialEventTarget> mBackgroundThread;
public:
explicit UnmapBlobCallback(SafeRefPtr<Database> aDatabase)
: mDatabase(std::move(aDatabase)) {
: mDatabase(std::move(aDatabase)),
mBackgroundThread(GetCurrentSerialEventTarget()) {
AssertIsOnBackgroundThread();
}
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(Database::UnmapBlobCallback, override)
void ActorDestroyed(const nsID& aID) override {
AssertIsOnBackgroundThread();
MOZ_ASSERT(mDatabase);
const SafeRefPtr<Database> database = std::move(mDatabase);
database->UnmapBlob(aID);
mBackgroundThread->Dispatch(NS_NewRunnableFunction(
"UnmapBlobCallback", [aID, database = std::move(mDatabase)] {
AssertIsOnBackgroundThread();
database->UnmapBlob(aID);
}));
}
private:
@ -9670,18 +9673,21 @@ void Database::MapBlob(const IPCBlob& aIPCBlob,
AssertIsOnBackgroundThread();
const RemoteLazyStream& stream = aIPCBlob.inputStream();
MOZ_ASSERT(stream.type() == RemoteLazyStream::TPRemoteLazyInputStreamParent);
MOZ_ASSERT(stream.type() == RemoteLazyStream::TRemoteLazyInputStream);
RemoteLazyInputStreamParent* actor =
static_cast<RemoteLazyInputStreamParent*>(
stream.get_PRemoteLazyInputStreamParent());
nsID id{};
MOZ_ALWAYS_SUCCEEDS(
stream.get_RemoteLazyInputStream()->GetInternalStreamID(id));
MOZ_ASSERT(!mMappedBlobs.Contains(actor->ID()));
mMappedBlobs.InsertOrUpdate(actor->ID(), std::move(aFileInfo));
MOZ_ASSERT(!mMappedBlobs.Contains(id));
mMappedBlobs.InsertOrUpdate(id, std::move(aFileInfo));
RefPtr<UnmapBlobCallback> callback =
new UnmapBlobCallback(SafeRefPtrFromThis());
actor->SetCallback(callback);
auto storage = RemoteLazyInputStreamStorage::Get();
MOZ_ASSERT(storage.isOk());
storage.inspect()->StoreCallback(id, callback);
}
void Database::Stringify(nsACString& aResult) const {
@ -9722,26 +9728,39 @@ void Database::Stringify(nsACString& aResult) const {
SafeRefPtr<DatabaseFileInfo> Database::GetBlob(const IPCBlob& aIPCBlob) {
AssertIsOnBackgroundThread();
const RemoteLazyStream& stream = aIPCBlob.inputStream();
MOZ_ASSERT(stream.type() == RemoteLazyStream::TIPCStream);
RefPtr<RemoteLazyInputStream> lazyStream;
switch (aIPCBlob.inputStream().type()) {
case RemoteLazyStream::TIPCStream: {
const InputStreamParams& inputStreamParams =
aIPCBlob.inputStream().get_IPCStream().stream();
if (inputStreamParams.type() !=
InputStreamParams::TRemoteLazyInputStreamParams) {
return nullptr;
}
lazyStream = inputStreamParams.get_RemoteLazyInputStreamParams().stream();
break;
}
case RemoteLazyStream::TRemoteLazyInputStream:
lazyStream = aIPCBlob.inputStream().get_RemoteLazyInputStream();
break;
default:
MOZ_ASSERT_UNREACHABLE("Unknown RemoteLazyStream type");
return nullptr;
}
const IPCStream& ipcStream = stream.get_IPCStream();
const InputStreamParams& inputStreamParams = ipcStream.stream();
if (inputStreamParams.type() !=
InputStreamParams::TRemoteLazyInputStreamParams) {
if (!lazyStream) {
MOZ_ASSERT_UNREACHABLE("Unexpected null stream");
return nullptr;
}
const RemoteLazyInputStreamParams& ipcBlobInputStreamParams =
inputStreamParams.get_RemoteLazyInputStreamParams();
if (ipcBlobInputStreamParams.type() !=
RemoteLazyInputStreamParams::TRemoteLazyInputStreamRef) {
nsID id{};
nsresult rv = lazyStream->GetInternalStreamID(id);
if (NS_FAILED(rv)) {
MOZ_ASSERT_UNREACHABLE(
"Received RemoteLazyInputStream doesn't have an actor connection");
return nullptr;
}
const nsID& id = ipcBlobInputStreamParams.get_RemoteLazyInputStreamRef().id();
const auto fileInfo = mMappedBlobs.Lookup(id);
return fileInfo ? fileInfo->clonePtr() : nullptr;
}

View File

@ -5,7 +5,6 @@
include protocol PBackgroundIDBTransaction;
include protocol PBackgroundIDBVersionChangeTransaction;
include protocol PBackgroundMutableFile;
include protocol PRemoteLazyInputStream; // FIXME: bug 792908
include PBackgroundIDBSharedTypes;

View File

@ -8,7 +8,6 @@ include protocol PBackgroundIDBFactory;
include protocol PBackgroundIDBTransaction;
include protocol PBackgroundIDBVersionChangeTransaction;
include protocol PBackgroundMutableFile;
include protocol PRemoteLazyInputStream; // FIXME: bug 792908
include IPCBlob;
include InputStreamParams;

View File

@ -5,7 +5,6 @@
include protocol PBackgroundIDBTransaction;
include protocol PBackgroundIDBVersionChangeTransaction;
include protocol PBackgroundMutableFile;
include protocol PRemoteLazyInputStream; // FIXME: bug 792908
include PBackgroundIDBSharedTypes;

View File

@ -4,7 +4,6 @@
include protocol PBackgroundIDBDatabaseFile;
include protocol PBackgroundMutableFile;
include protocol PRemoteLazyInputStream; // FIXME: bug 792908
include DOMTypes;
include IPCBlob;

View File

@ -7,7 +7,6 @@ include protocol PBackgroundIDBDatabase;
include protocol PBackgroundIDBDatabaseFile;
include protocol PBackgroundIDBRequest;
include protocol PBackgroundMutableFile;
include protocol PRemoteLazyInputStream; // FIXME: bug 792908
include PBackgroundIDBSharedTypes;

View File

@ -1878,14 +1878,6 @@ void ContentChild::GetAvailableDictionaries(
aDictionaries = mAvailableDictionaries.Clone();
}
already_AddRefed<PRemoteLazyInputStreamChild>
ContentChild::AllocPRemoteLazyInputStreamChild(const nsID& aID,
const uint64_t& aSize) {
RefPtr<RemoteLazyInputStreamChild> actor =
new RemoteLazyInputStreamChild(aID, aSize);
return actor.forget();
}
mozilla::PRemoteSpellcheckEngineChild*
ContentChild::AllocPRemoteSpellcheckEngineChild() {
MOZ_CRASH(

View File

@ -177,9 +177,6 @@ class ContentChild final : public PContentChild,
mozilla::ipc::IPCResult RecvSetProcessSandbox(
const Maybe<FileDescriptor>& aBroker);
already_AddRefed<PRemoteLazyInputStreamChild>
AllocPRemoteLazyInputStreamChild(const nsID& aID, const uint64_t& aSize);
PHalChild* AllocPHalChild();
bool DeallocPHalChild(PHalChild*);

View File

@ -17,7 +17,6 @@ include "mozilla/net/ClassOfService.h";
include IPCBlob;
include IPCStream;
include protocol PRemoteLazyInputStream;
include ProtocolTypes;
using struct mozilla::void_t from "mozilla/ipc/IPCCore.h";
@ -52,6 +51,7 @@ using mozilla::dom::MaybeDiscardedBrowsingContext from "mozilla/dom/BrowsingCont
[RefCounted] using class nsIVariant from "nsIVariant.h";
using mozilla::TimeStamp from "mozilla/TimeStamp.h";
[RefCounted] using class mozilla::dom::BrowsingContext from "mozilla/dom/BrowsingContext.h";
[RefCounted] using class mozilla::RemoteLazyInputStream from "mozilla/RemoteLazyInputStream.h";
namespace mozilla {
namespace dom {
@ -345,7 +345,8 @@ struct ReplacementChannelConfigInit
nsCString? method;
nsIReferrerInfo referrerInfo;
TimedChannelInfo? timedChannelInfo;
nullable PRemoteLazyInputStream uploadStream;
RemoteLazyInputStream uploadStream;
uint64_t uploadStreamLength;
bool uploadStreamHasHeaders;
nsCString? contentType;
nsCString? contentLength;

View File

@ -12,7 +12,6 @@ include protocol PDocAccessible;
#endif
include protocol PFilePicker;
include protocol PRemotePrintJob;
include protocol PRemoteLazyInputStream;
include protocol PPaymentRequest;
include protocol PSessionStore;
include protocol PWindowGlobal;

View File

@ -17,7 +17,6 @@ include protocol PHal;
include protocol PHeapSnapshotTempFileHelper;
include protocol PProcessHangMonitor;
include protocol PImageBridge;
include protocol PRemoteLazyInputStream;
include protocol PRemotePrintJob;
include protocol PLoginReputation;
include protocol PMedia;
@ -463,7 +462,6 @@ sync protocol PContent
manages PHal;
manages PHandlerService;
manages PHeapSnapshotTempFileHelper;
manages PRemoteLazyInputStream;
manages PRemotePrintJob;
manages PMedia;
manages PNecko;
@ -861,8 +859,6 @@ child:
async RefreshScreens(ScreenDetails[] aScreens);
async PRemoteLazyInputStream(nsID aID, uint64_t aSize);
async ShareCodeCoverageMutex(CrossProcessMutexHandle handle);
async FlushCodeCoverageCounters() returns (bool unused);

View File

@ -5,7 +5,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
include protocol PBrowser;
include protocol PRemoteLazyInputStream;
include IPCBlob;

View File

@ -3,7 +3,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
include protocol PBackground;
include protocol PRemoteLazyInputStream; // FIXME: bug 792908
include DOMTypes;
include ProtocolTypes;

View File

@ -25,7 +25,6 @@
#include "mozilla/dom/FetchEventOpParent.h"
#include "mozilla/ipc/BackgroundParent.h"
#include "mozilla/ipc/IPCStreamUtils.h"
#include "mozilla/RemoteLazyInputStreamUtils.h"
#include "mozilla/RemoteLazyInputStreamStorage.h"
namespace mozilla {
@ -58,7 +57,7 @@ nsresult MaybeDeserializeAndWrapForMainThread(
}
auto storage = storageOrErr.unwrap();
storage->AddStream(deserialized, uuid, aBodyStreamSize, 0);
storage->AddStream(deserialized, uuid);
return NS_OK;
}
@ -156,17 +155,13 @@ ParentToParentFetchEventRespondWithResult ToParentToParent(
IPCInternalRequest& copyRequest = copyArgs.common().internalRequest();
if (aBodyStream) {
PBackgroundParent* bgParent = aManager->Manager();
MOZ_ASSERT(bgParent);
copyRequest.body() = Some(ParentToChildStream());
RemoteLazyStream ipdlStream;
MOZ_ALWAYS_SUCCEEDS(RemoteLazyInputStreamUtils::SerializeInputStream(
aBodyStream, copyRequest.bodySize(), ipdlStream, bgParent));
RefPtr<RemoteLazyInputStream> stream =
RemoteLazyInputStream::WrapStream(aBodyStream);
MOZ_DIAGNOSTIC_ASSERT(stream);
copyRequest.body().ref().get_ParentToChildStream().actorParent() =
ipdlStream;
copyRequest.body().ref().get_ParentToChildStream().stream() = stream;
}
Unused << aManager->SendPFetchEventOpProxyConstructor(actor, copyArgs);

View File

@ -863,7 +863,6 @@ nsresult MaybeStoreStreamForBackgroundThread(nsIInterceptedChannel* aChannel,
MOZ_ALWAYS_SUCCEEDS(aChannel->GetChannel(getter_AddRefs(channel)));
Maybe<BodyStreamVariant> body;
int64_t bodySize = -1;
nsCOMPtr<nsIUploadChannel2> uploadChannel = do_QueryInterface(channel);
if (uploadChannel) {
@ -884,8 +883,7 @@ nsresult MaybeStoreStreamForBackgroundThread(nsIInterceptedChannel* aChannel,
}
auto storage = storageOrErr.unwrap();
storage->AddStream(uploadStream, body->get_ParentToParentStream().uuid(),
bodySize, 0);
storage->AddStream(uploadStream, body->get_ParentToParentStream().uuid());
}
}

View File

@ -13,7 +13,6 @@
#include "mozilla/Assertions.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/Maybe.h"
#include "mozilla/RemoteLazyInputStreamUtils.h"
#include "mozilla/RemoteLazyInputStreamStorage.h"
#include "mozilla/dom/FetchEventOpParent.h"
#include "mozilla/dom/FetchEventOpProxyParent.h"

View File

@ -383,14 +383,6 @@ bool BackgroundChildImpl::DeallocPFileCreatorChild(PFileCreatorChild* aActor) {
return true;
}
already_AddRefed<PRemoteLazyInputStreamChild>
BackgroundChildImpl::AllocPRemoteLazyInputStreamChild(const nsID& aID,
const uint64_t& aSize) {
RefPtr<RemoteLazyInputStreamChild> actor =
new RemoteLazyInputStreamChild(aID, aSize);
return actor.forget();
}
PUDPSocketChild* BackgroundChildImpl::AllocPUDPSocketChild(
const Maybe<PrincipalInfo>& aPrincipalInfo, const nsCString& aFilter) {
MOZ_CRASH("AllocPUDPSocket should not be called");

View File

@ -108,10 +108,6 @@ class BackgroundChildImpl : public PBackgroundChild,
virtual bool DeallocPBackgroundStorageChild(
PBackgroundStorageChild* aActor) override;
virtual already_AddRefed<PRemoteLazyInputStreamChild>
AllocPRemoteLazyInputStreamChild(const nsID& aID,
const uint64_t& aSize) override;
virtual PTemporaryIPCBlobChild* AllocPTemporaryIPCBlobChild() override;
virtual bool DeallocPTemporaryIPCBlobChild(

View File

@ -654,20 +654,6 @@ bool BackgroundParentImpl::DeallocPTemporaryIPCBlobParent(
return true;
}
already_AddRefed<PRemoteLazyInputStreamParent>
BackgroundParentImpl::AllocPRemoteLazyInputStreamParent(const nsID& aID,
const uint64_t& aSize) {
AssertIsInMainOrSocketProcess();
AssertIsOnBackgroundThread();
// There is nothing to construct here, so we do not implement
// RecvPRemoteLazyInputStreamConstructor.
RefPtr<RemoteLazyInputStreamParent> actor =
RemoteLazyInputStreamParent::Create(aID, aSize, this);
return actor.forget();
}
already_AddRefed<BackgroundParentImpl::PVsyncParent>
BackgroundParentImpl::AllocPVsyncParent() {
AssertIsInMainOrSocketProcess();

View File

@ -137,10 +137,6 @@ class BackgroundParentImpl : public PBackgroundParent,
already_AddRefed<PIdleSchedulerParent> AllocPIdleSchedulerParent() override;
already_AddRefed<PRemoteLazyInputStreamParent>
AllocPRemoteLazyInputStreamParent(const nsID& aID,
const uint64_t& aSize) override;
PTemporaryIPCBlobParent* AllocPTemporaryIPCBlobParent() override;
mozilla::ipc::IPCResult RecvPTemporaryIPCBlobConstructor(

View File

@ -112,43 +112,13 @@ bool SerializeLazyInputStream(nsIInputStream* aStream, IPCStream& aValue,
MOZ_ASSERT(aManager);
MOZ_ASSERT(XRE_IsParentProcess());
// avoid creating a loop between processes by accessing the underlying input
// stream.
nsCOMPtr<nsIInputStream> stream = aStream;
if (nsCOMPtr<mozIRemoteLazyInputStream> remoteLazyInputStream =
do_QueryInterface(stream)) {
stream = remoteLazyInputStream->GetInternalStream();
if (NS_WARN_IF(!stream)) {
return false;
}
}
uint64_t childID = 0;
if constexpr (std::is_same_v<dom::ContentParent, M>) {
childID = aManager->ChildID();
} else if constexpr (std::is_base_of_v<PBackgroundParent, M>) {
childID = BackgroundParent::GetChildID(aManager);
}
int64_t length = -1;
if (!InputStreamLengthHelper::GetSyncLength(stream, &length)) {
length = -1;
}
nsresult rv = NS_OK;
RefPtr<RemoteLazyInputStreamParent> actor =
RemoteLazyInputStreamParent::Create(aStream, length, childID, &rv,
aManager);
if (NS_WARN_IF(NS_FAILED(rv))) {
RefPtr<RemoteLazyInputStream> lazyStream =
RemoteLazyInputStream::WrapStream(aStream);
if (NS_WARN_IF(!lazyStream)) {
return false;
}
if (!aManager->SendPRemoteLazyInputStreamConstructor(actor, actor->ID(),
actor->Size())) {
return false;
}
aValue.stream() = RemoteLazyInputStreamParams(actor);
aValue.stream() = RemoteLazyInputStreamParams(lazyStream);
return true;
}

View File

@ -171,6 +171,8 @@ class AutoIPCStream {
[[nodiscard]] bool Serialize(nsIInputStream* aStream,
net::SocketProcessParent* aManager);
bool Serialize(nsIInputStream* aStream);
// Get the IPCStream as a non-optional value. This will
// assert if a stream has not been serialized or if it has already been taken.
// This should only be called if the value is being, or has already been, sent

View File

@ -4,10 +4,9 @@
include ProtocolTypes;
include protocol PRemoteLazyInputStream;
using struct mozilla::void_t from "mozilla/ipc/IPCCore.h";
[RefCounted] using class DataPipeReceiver from "mozilla/ipc/DataPipe.h";
[RefCounted] using class mozilla::RemoteLazyInputStream from "mozilla/RemoteLazyInputStream.h";
namespace mozilla {
namespace ipc {
@ -47,17 +46,9 @@ struct SlicedInputStreamParams
bool closed;
};
struct RemoteLazyInputStreamRef
struct RemoteLazyInputStreamParams
{
nsID id;
uint64_t start;
uint64_t length;
};
union RemoteLazyInputStreamParams
{
RemoteLazyInputStreamRef;
PRemoteLazyInputStream;
RemoteLazyInputStream stream;
};
struct DataPipeReceiverStreamParams

View File

@ -51,7 +51,6 @@ void SerializeInputStreamInternal(nsIInputStream* aInputStream,
bool aDelayedStart, uint32_t aMaxSize,
uint32_t* aSizeUsed, M* aManager) {
MOZ_ASSERT(aInputStream);
MOZ_ASSERT(aManager);
nsCOMPtr<nsIIPCSerializableInputStream> serializable =
do_QueryInterface(aInputStream);
@ -72,7 +71,6 @@ void SerializeInputStreamAsPipeInternal(nsIInputStream* aInputStream,
InputStreamParams& aParams,
bool aDelayedStart, M* aManager) {
MOZ_ASSERT(aInputStream);
MOZ_ASSERT(aManager);
// Let's try to take the length using InputStreamLengthHelper. If the length
// cannot be taken synchronously, and its length is needed, the stream needs
@ -164,31 +162,17 @@ already_AddRefed<nsIInputStream> InputStreamHelper::DeserializeInputStream(
const RemoteLazyInputStreamParams& params =
aParams.get_RemoteLazyInputStreamParams();
// RemoteLazyInputStreamRefs are not deserializable on the parent side,
// because the parent is the only one that has a copy of the original stream
// in the RemoteLazyInputStreamStorage.
if (params.type() ==
RemoteLazyInputStreamParams::TRemoteLazyInputStreamRef) {
MOZ_ASSERT(XRE_IsParentProcess());
const RemoteLazyInputStreamRef& ref =
params.get_RemoteLazyInputStreamRef();
auto storage = RemoteLazyInputStreamStorage::Get().unwrapOr(nullptr);
MOZ_ASSERT(storage);
nsCOMPtr<nsIInputStream> stream;
storage->GetStream(ref.id(), ref.start(), ref.length(),
getter_AddRefs(stream));
return stream.forget();
// If the RemoteLazyInputStream already has an internal stream, unwrap it.
// This is required as some code unfortunately depends on the precise
// topology of received streams, and cannot handle being passed a
// `RemoteLazyInputStream` in the parent process.
nsCOMPtr<nsIInputStream> innerStream;
if (XRE_IsParentProcess() &&
NS_SUCCEEDED(
params.stream()->TakeInternalStream(getter_AddRefs(innerStream)))) {
return innerStream.forget();
}
// parent -> child serializations receive an RemoteLazyInputStream actor.
MOZ_ASSERT(params.type() ==
RemoteLazyInputStreamParams::TPRemoteLazyInputStreamChild);
RemoteLazyInputStreamChild* actor =
static_cast<RemoteLazyInputStreamChild*>(
params.get_PRemoteLazyInputStreamChild());
nsCOMPtr<nsIInputStream> stream = actor->CreateStream();
return stream.forget();
return do_AddRef(params.stream());
}
if (aParams.type() == InputStreamParams::TDataPipeReceiverStreamParams) {

View File

@ -27,7 +27,6 @@ include protocol PGamepadTestChannel;
include protocol PHttpBackgroundChannel;
include protocol PIPCClientCerts;
include protocol PIdleScheduler;
include protocol PRemoteLazyInputStream;
include protocol PMediaTransport;
include protocol PRemoteWorker;
include protocol PRemoteWorkerController;
@ -106,7 +105,6 @@ sync protocol PBackground
manages PHttpBackgroundChannel;
manages PIPCClientCerts;
manages PIdleScheduler;
manages PRemoteLazyInputStream;
manages PLockManager;
manages PMediaTransport;
manages PRemoteWorker;
@ -294,11 +292,6 @@ child:
async PCacheStreamControl();
async PRemoteWorker(RemoteWorkerData data);
both:
// PRemoteLazyInputStream is created on the parent side only if the child
// starts a migration.
async PRemoteLazyInputStream(nsID aID, uint64_t aSize);
};
} // namespace ipc

View File

@ -16,7 +16,6 @@ include protocol PAltSvcTransaction;
include protocol PTRRService;
include protocol PProxyConfigLookup;
include protocol PNativeDNSResolverOverride;
include protocol PRemoteLazyInputStream;
include protocol PProxyAutoConfig;
#if defined(MOZ_SANDBOX) && defined(MOZ_DEBUG) && defined(ENABLE_TESTS)
@ -101,7 +100,6 @@ sync protocol PSocketProcess
manages PTRRService;
manages PProxyConfigLookup;
manages PNativeDNSResolverOverride;
manages PRemoteLazyInputStream;
parent:
async InitCrashReporter(NativeThreadId threadId);
@ -191,8 +189,6 @@ child:
async PNativeDNSResolverOverride();
async NotifyObserver(nsCString aTopic, nsString aData);
async PRemoteLazyInputStream(nsID aID, uint64_t aSize);
async GetSocketData()
returns (SocketDataArgs data);
async GetDNSCacheEntries()

View File

@ -503,14 +503,6 @@ mozilla::ipc::IPCResult SocketProcessChild::RecvNotifyObserver(
return IPC_OK();
}
already_AddRefed<PRemoteLazyInputStreamChild>
SocketProcessChild::AllocPRemoteLazyInputStreamChild(const nsID& aID,
const uint64_t& aSize) {
RefPtr<RemoteLazyInputStreamChild> actor =
new RemoteLazyInputStreamChild(aID, aSize);
return actor.forget();
}
namespace {
class DataResolverBase {

View File

@ -124,9 +124,6 @@ class SocketProcessChild final
mozilla::ipc::IPCResult RecvNotifyObserver(const nsCString& aTopic,
const nsString& aData);
virtual already_AddRefed<PRemoteLazyInputStreamChild>
AllocPRemoteLazyInputStreamChild(const nsID& aID, const uint64_t& aSize);
mozilla::ipc::IPCResult RecvGetSocketData(GetSocketDataResolver&& aResolve);
mozilla::ipc::IPCResult RecvGetDNSCacheEntries(
GetDNSCacheEntriesResolver&& aResolve);

View File

@ -360,16 +360,6 @@ void SocketProcessParent::Destroy(UniquePtr<SocketProcessParent>&& aParent) {
new DeferredDeleteSocketProcessParent(std::move(aParent)));
}
already_AddRefed<PRemoteLazyInputStreamParent>
SocketProcessParent::AllocPRemoteLazyInputStreamParent(const nsID& aID,
const uint64_t& aSize) {
// There is nothing to construct here, so we do not implement
// RecvPRemoteLazyInputStreamConstructor.
RefPtr<RemoteLazyInputStreamParent> actor =
RemoteLazyInputStreamParent::Create(aID, aSize, this);
return actor.forget();
}
mozilla::ipc::IPCResult SocketProcessParent::RecvODoHServiceActivated(
const bool& aActivated) {
nsCOMPtr<nsIObserverService> observerService =

View File

@ -104,9 +104,6 @@ class SocketProcessParent final
nsIURI* aPushedURL, OriginAttributes&& aOriginAttributes,
nsCString&& aRequestString, CachePushCheckResolver&& aResolver);
already_AddRefed<PRemoteLazyInputStreamParent>
AllocPRemoteLazyInputStreamParent(const nsID& aID, const uint64_t& aSize);
mozilla::ipc::IPCResult RecvODoHServiceActivated(const bool& aActivated);
mozilla::ipc::IPCResult RecvExcludeHttp2OrHttp3(

View File

@ -93,7 +93,6 @@
#include "nsThreadUtils.h"
#include "nsURLHelper.h"
#include "mozilla/RemoteLazyInputStreamChild.h"
#include "mozilla/RemoteLazyInputStreamUtils.h"
#include "mozilla/net/SFVService.h"
#include "mozilla/dom/ContentChild.h"
#include "nsQueryObject.h"
@ -4340,15 +4339,8 @@ HttpBaseChannel::ReplacementChannelConfig::ReplacementChannelConfig(
method = aInit.method();
referrerInfo = aInit.referrerInfo();
timedChannelInfo = aInit.timedChannelInfo();
if (RemoteLazyInputStreamChild* actor =
static_cast<RemoteLazyInputStreamChild*>(aInit.uploadStreamChild())) {
uploadStreamLength = actor->Size();
uploadStream = actor->CreateStream();
// actor can be deleted by CreateStream, so don't touch it
// after this.
} else {
uploadStreamLength = 0;
}
uploadStream = aInit.uploadStream();
uploadStreamLength = aInit.uploadStreamLength();
uploadStreamHasHeaders = aInit.uploadStreamHasHeaders();
contentType = aInit.contentType();
contentLength = aInit.contentLength();
@ -4364,12 +4356,9 @@ HttpBaseChannel::ReplacementChannelConfig::Serialize(
config.method() = method;
config.referrerInfo() = referrerInfo;
config.timedChannelInfo() = timedChannelInfo;
if (uploadStream) {
RemoteLazyStream ipdlStream;
RemoteLazyInputStreamUtils::SerializeInputStream(
uploadStream, uploadStreamLength, ipdlStream, aParent);
config.uploadStreamParent() = ipdlStream;
}
config.uploadStream() =
uploadStream ? RemoteLazyInputStream::WrapStream(uploadStream) : nullptr;
config.uploadStreamLength() = uploadStreamLength;
config.uploadStreamHasHeaders() = uploadStreamHasHeaders;
config.contentType() = contentType;
config.contentLength() = contentLength;