Backed out 22 changesets (bug 1696894, bug 1759569, bug 1754031, bug 1759563, bug 1759572, bug 1754004) for causing leack failures CLOSED TREE

Backed out changeset 673ecd5337e1 (bug 1754004)
Backed out changeset ecbf5f3c51de (bug 1754004)
Backed out changeset fc6c39f56d21 (bug 1754004)
Backed out changeset 5b3d58fbaf9d (bug 1696894)
Backed out changeset 2e56c89cf55d (bug 1754004)
Backed out changeset b7723490f025 (bug 1754004)
Backed out changeset 1dfbf61ff5dd (bug 1754004)
Backed out changeset e73abb071bb3 (bug 1754004)
Backed out changeset f9abe4fbf501 (bug 1754004)
Backed out changeset ee7aeb631cd9 (bug 1754004)
Backed out changeset d66aacfcf983 (bug 1754004)
Backed out changeset 5c2872ad6912 (bug 1754004)
Backed out changeset e1ae48f30d2c (bug 1754004)
Backed out changeset 849b63707d7f (bug 1754004)
Backed out changeset 36563e3b1e04 (bug 1754004)
Backed out changeset ccb4be659107 (bug 1754004)
Backed out changeset 659581d4159b (bug 1754004)
Backed out changeset 611ea76d7a9c (bug 1754004)
Backed out changeset 9b24b561698c (bug 1759572)
Backed out changeset f820e0f209ff (bug 1759563)
Backed out changeset 8d82066fa181 (bug 1759569)
Backed out changeset a2835afab1ad (bug 1754031)
This commit is contained in:
Noemi Erli 2022-05-11 06:16:25 +03:00
Родитель c142fc6abc
Коммит 45276205df
176 изменённых файлов: 7974 добавлений и 2565 удалений

Просмотреть файл

@ -4,6 +4,7 @@
* 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 PFileDescriptorSet;
include protocol PBrowser;
include protocol PDocAccessiblePlatformExt;

Просмотреть файл

@ -4,6 +4,7 @@
* 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 PFileDescriptorSet;
include protocol PBrowser;
include DocAccessibleTypes;

Просмотреть файл

@ -3508,7 +3508,7 @@ bool BrowsingContext::IsPopupAllowed() {
bool BrowsingContext::ShouldAddEntryForRefresh(
nsIURI* aCurrentURI, const SessionHistoryInfo& aInfo) {
return ShouldAddEntryForRefresh(aCurrentURI, aInfo.GetURI(),
aInfo.HasPostData());
aInfo.GetPostData());
}
/* static */

Просмотреть файл

@ -475,7 +475,7 @@ class CanonicalBrowsingContext final : public BrowsingContext {
bool ShouldAddEntryForRefresh(const SessionHistoryEntry* aEntry) {
return ShouldAddEntryForRefresh(aEntry->Info().GetURI(),
aEntry->Info().HasPostData());
aEntry->Info().GetPostData());
}
bool ShouldAddEntryForRefresh(nsIURI* aNewURI, bool aHasPostData) {
nsCOMPtr<nsIURI> currentURI = GetCurrentURI();

Просмотреть файл

@ -8800,6 +8800,19 @@ bool nsDocShell::IsSameDocumentNavigation(nsDocShellLoadState* aLoadState,
}
}
#ifdef DEBUG
if (aState.mHistoryNavBetweenSameDoc) {
nsCOMPtr<nsIInputStream> currentPostData;
if (mozilla::SessionHistoryInParent()) {
currentPostData = mActiveEntry->GetPostData();
} else {
currentPostData = mOSHE->GetPostData();
}
NS_ASSERTION(currentPostData == aLoadState->PostDataStream(),
"Different POST data for entries for the same page?");
}
#endif
// A same document navigation happens when we navigate between two SHEntries
// for the same document. We do a same document navigation under two
// circumstances. Either
@ -10028,10 +10041,6 @@ nsIPrincipal* nsDocShell::GetInheritedPrincipal(
// we really need to have a content type associated with this stream!!
postChannel->SetUploadStream(aLoadState->PostDataStream(), ""_ns, -1);
// Ownership of the stream has transferred to the channel, clear our
// reference.
aLoadState->SetPostDataStream(nullptr);
}
/* If there is a valid postdata *and* it is a History Load,

Просмотреть файл

@ -9,13 +9,10 @@
#include "nsDocShell.h"
#include "nsDocShellLoadState.h"
#include "nsFrameLoader.h"
#include "nsIFormPOSTActionChannel.h"
#include "nsIHttpChannel.h"
#include "nsIUploadChannel2.h"
#include "nsIXULRuntime.h"
#include "nsSHEntryShared.h"
#include "nsSHistory.h"
#include "nsStreamUtils.h"
#include "nsStructuredCloneContainer.h"
#include "nsXULAppAPI.h"
#include "mozilla/PresState.h"
@ -45,6 +42,7 @@ SessionHistoryInfo::SessionHistoryInfo(nsDocShellLoadState* aLoadState,
: mURI(aLoadState->URI()),
mOriginalURI(aLoadState->OriginalURI()),
mResultPrincipalURI(aLoadState->ResultPrincipalURI()),
mPostData(aLoadState->PostDataStream()),
mLoadType(aLoadState->LoadType()),
mSrcdocData(aLoadState->SrcdocData().IsVoid()
? Nothing()
@ -58,15 +56,6 @@ SessionHistoryInfo::SessionHistoryInfo(nsDocShellLoadState* aLoadState,
aLoadState->PartitionedPrincipalToInherit(), aLoadState->Csp(),
/* FIXME Is this correct? */
aLoadState->TypeHint())) {
// Pull the upload stream off of the channel instead of the load state, as
// ownership has already been transferred from the load state to the channel.
if (nsCOMPtr<nsIUploadChannel2> postChannel = do_QueryInterface(aChannel)) {
int64_t contentLength;
MOZ_ALWAYS_SUCCEEDS(postChannel->CloneUploadStream(
&contentLength, getter_AddRefs(mPostData)));
MOZ_ASSERT_IF(mPostData, NS_InputStreamIsCloneable(mPostData));
}
if (nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aChannel)) {
mReferrerInfo = httpChannel->GetReferrerInfo();
}
@ -174,24 +163,6 @@ void SessionHistoryInfo::MaybeUpdateTitleFromURI() {
}
}
already_AddRefed<nsIInputStream> SessionHistoryInfo::GetPostData() const {
// Return a clone of our post data stream. Our caller will either be
// transferring this stream to a different SessionHistoryInfo, or passing it
// off to necko/another process which will consume it, and we want to preserve
// our local instance.
nsCOMPtr<nsIInputStream> postData;
if (mPostData) {
MOZ_ALWAYS_SUCCEEDS(
NS_CloneInputStream(mPostData, getter_AddRefs(postData)));
}
return postData.forget();
}
void SessionHistoryInfo::SetPostData(nsIInputStream* aPostData) {
MOZ_ASSERT_IF(aPostData, NS_InputStreamIsCloneable(aPostData));
mPostData = aPostData;
}
uint64_t SessionHistoryInfo::SharedId() const {
return mSharedState.Get()->mId;
}
@ -246,8 +217,7 @@ void SessionHistoryInfo::FillLoadInfo(nsDocShellLoadState& aLoadState) const {
aLoadState.SetOriginalURI(mOriginalURI);
aLoadState.SetMaybeResultPrincipalURI(Some(mResultPrincipalURI));
aLoadState.SetLoadReplace(mLoadReplace);
nsCOMPtr<nsIInputStream> postData = GetPostData();
aLoadState.SetPostDataStream(postData);
aLoadState.SetPostDataStream(mPostData);
aLoadState.SetReferrerInfo(mReferrerInfo);
aLoadState.SetTypeHint(mSharedState.Get()->mContentType);
@ -683,13 +653,14 @@ SessionHistoryEntry::SetRefreshURIList(nsIMutableArray* aRefreshURIList) {
NS_IMETHODIMP
SessionHistoryEntry::GetPostData(nsIInputStream** aPostData) {
*aPostData = mInfo->GetPostData().take();
nsCOMPtr<nsIInputStream> postData = mInfo->mPostData;
postData.forget(aPostData);
return NS_OK;
}
NS_IMETHODIMP
SessionHistoryEntry::SetPostData(nsIInputStream* aPostData) {
mInfo->SetPostData(aPostData);
mInfo->mPostData = aPostData;
return NS_OK;
}
@ -1496,8 +1467,6 @@ namespace ipc {
void IPDLParamTraits<dom::SessionHistoryInfo>::Write(
IPC::MessageWriter* aWriter, IProtocol* aActor,
const dom::SessionHistoryInfo& aParam) {
nsCOMPtr<nsIInputStream> postData = aParam.GetPostData();
Maybe<Tuple<uint32_t, dom::ClonedMessageData>> stateData;
if (aParam.mStateData) {
stateData.emplace();
@ -1528,7 +1497,7 @@ void IPDLParamTraits<dom::SessionHistoryInfo>::Write(
WriteIPDLParam(aWriter, aActor, aParam.mReferrerInfo);
WriteIPDLParam(aWriter, aActor, aParam.mTitle);
WriteIPDLParam(aWriter, aActor, aParam.mName);
WriteIPDLParam(aWriter, aActor, postData);
WriteIPDLParam(aWriter, aActor, aParam.mPostData);
WriteIPDLParam(aWriter, aActor, aParam.mLoadType);
WriteIPDLParam(aWriter, aActor, aParam.mScrollPositionX);
WriteIPDLParam(aWriter, aActor, aParam.mScrollPositionY);
@ -1601,17 +1570,6 @@ bool IPDLParamTraits<dom::SessionHistoryInfo>::Read(
return false;
}
// We should always see a cloneable input stream passed to SessionHistoryInfo.
// This is because it will be cloneable when first read in the parent process
// from the nsHttpChannel (which forces streams to be cloneable), and future
// streams in content will be wrapped in
// nsMIMEInputStream(RemoteLazyInputStream) which is also cloneable.
if (aResult->mPostData && !NS_InputStreamIsCloneable(aResult->mPostData)) {
aActor->FatalError(
"Unexpected non-cloneable postData for SessionHistoryInfo");
return false;
}
dom::SHEntrySharedParentState* sharedState = nullptr;
if (XRE_IsParentProcess()) {
sharedState = dom::SHEntrySharedParentState::Lookup(sharedId);

Просмотреть файл

@ -71,9 +71,8 @@ class SessionHistoryInfo {
mResultPrincipalURI = aResultPrincipalURI;
}
bool HasPostData() const { return mPostData; }
already_AddRefed<nsIInputStream> GetPostData() const;
void SetPostData(nsIInputStream* aPostData);
nsIInputStream* GetPostData() const { return mPostData; }
void SetPostData(nsIInputStream* aPostData) { mPostData = aPostData; }
void GetScrollPosition(int32_t* aScrollPositionX, int32_t* aScrollPositionY) {
*aScrollPositionX = mScrollPositionX;

Просмотреть файл

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

55
dom/cache/AutoUtils.cpp поставляемый
Просмотреть файл

@ -23,6 +23,7 @@
using mozilla::Maybe;
using mozilla::Unused;
using mozilla::dom::cache::CacheReadStream;
using mozilla::ipc::AutoIPCStream;
using mozilla::ipc::PBackgroundParent;
namespace {
@ -31,6 +32,7 @@ enum CleanupAction { Forget, Delete };
void CleanupChild(CacheReadStream& aReadStream, CleanupAction aAction) {
// fds cleaned up by mStreamCleanupList
// PChildToParentStream actors cleaned up by mStreamCleanupList
}
void CleanupChild(Maybe<CacheReadStream>& aMaybeReadStream,
@ -54,6 +56,12 @@ AutoChildOpArgs::AutoChildOpArgs(TypeUtils* aTypeUtils,
: mTypeUtils(aTypeUtils), mOpArgs(aOpArgs), mSent(false) {
MOZ_DIAGNOSTIC_ASSERT(mTypeUtils);
MOZ_RELEASE_ASSERT(aEntryCount != 0);
// We are using AutoIPCStream objects to cleanup target IPCStream
// structures embedded in our CacheOpArgs. These IPCStream structs
// must not move once we attach our AutoIPCStream to them. Therefore,
// its important that any arrays containing streams are pre-sized for
// the number of entries we have in order to avoid realloc moving
// things around on us.
if (mOpArgs.type() == CacheOpArgs::TCachePutAllArgs) {
CachePutAllArgs& args = mOpArgs.get_CachePutAllArgs();
args.requestResponseList().SetCapacity(aEntryCount);
@ -110,6 +118,8 @@ AutoChildOpArgs::~AutoChildOpArgs() {
// Other types do not need cleanup
break;
}
mStreamCleanupList.Clear();
}
void AutoChildOpArgs::Add(const InternalRequest& aRequest,
@ -121,7 +131,7 @@ void AutoChildOpArgs::Add(const InternalRequest& aRequest,
case CacheOpArgs::TCacheMatchArgs: {
CacheMatchArgs& args = mOpArgs.get_CacheMatchArgs();
mTypeUtils->ToCacheRequest(args.request(), aRequest, aBodyAction,
aSchemeAction, aRv);
aSchemeAction, mStreamCleanupList, aRv);
break;
}
case CacheOpArgs::TCacheMatchAllArgs: {
@ -129,13 +139,14 @@ void AutoChildOpArgs::Add(const InternalRequest& aRequest,
MOZ_DIAGNOSTIC_ASSERT(args.maybeRequest().isNothing());
args.maybeRequest().emplace(CacheRequest());
mTypeUtils->ToCacheRequest(args.maybeRequest().ref(), aRequest,
aBodyAction, aSchemeAction, aRv);
aBodyAction, aSchemeAction, mStreamCleanupList,
aRv);
break;
}
case CacheOpArgs::TCacheDeleteArgs: {
CacheDeleteArgs& args = mOpArgs.get_CacheDeleteArgs();
mTypeUtils->ToCacheRequest(args.request(), aRequest, aBodyAction,
aSchemeAction, aRv);
aSchemeAction, mStreamCleanupList, aRv);
break;
}
case CacheOpArgs::TCacheKeysArgs: {
@ -143,13 +154,14 @@ void AutoChildOpArgs::Add(const InternalRequest& aRequest,
MOZ_DIAGNOSTIC_ASSERT(args.maybeRequest().isNothing());
args.maybeRequest().emplace(CacheRequest());
mTypeUtils->ToCacheRequest(args.maybeRequest().ref(), aRequest,
aBodyAction, aSchemeAction, aRv);
aBodyAction, aSchemeAction, mStreamCleanupList,
aRv);
break;
}
case CacheOpArgs::TStorageMatchArgs: {
StorageMatchArgs& args = mOpArgs.get_StorageMatchArgs();
mTypeUtils->ToCacheRequest(args.request(), aRequest, aBodyAction,
aSchemeAction, aRv);
aSchemeAction, mStreamCleanupList, aRv);
break;
}
default:
@ -262,6 +274,10 @@ void AutoChildOpArgs::Add(JSContext* aCx, const InternalRequest& aRequest,
return;
}
// Ensure that we don't realloc the array since this can result
// in our AutoIPCStream objects to reference the wrong memory
// location. This should never happen and is a UAF if it does.
// Therefore make this a release assertion.
MOZ_RELEASE_ASSERT(args.requestResponseList().Length() <
args.requestResponseList().Capacity());
@ -277,9 +293,10 @@ void AutoChildOpArgs::Add(JSContext* aCx, const InternalRequest& aRequest,
pair.response().body() = Nothing();
mTypeUtils->ToCacheRequest(pair.request(), aRequest, aBodyAction,
aSchemeAction, aRv);
aSchemeAction, mStreamCleanupList, aRv);
if (!aRv.Failed()) {
mTypeUtils->ToCacheResponse(aCx, pair.response(), aResponse, aRv);
mTypeUtils->ToCacheResponse(aCx, pair.response(), aResponse,
mStreamCleanupList, aRv);
}
if (aRv.Failed()) {
@ -297,6 +314,9 @@ void AutoChildOpArgs::Add(JSContext* aCx, const InternalRequest& aRequest,
const CacheOpArgs& AutoChildOpArgs::SendAsOpArgs() {
MOZ_DIAGNOSTIC_ASSERT(!mSent);
mSent = true;
for (UniquePtr<AutoIPCStream>& autoStream : mStreamCleanupList) {
autoStream->TakeOptionalValue();
}
return mOpArgs;
}
@ -311,6 +331,12 @@ AutoParentOpResult::AutoParentOpResult(
mSent(false) {
MOZ_DIAGNOSTIC_ASSERT(mManager);
MOZ_RELEASE_ASSERT(aEntryCount != 0);
// We are using AutoIPCStream objects to cleanup target IPCStream
// structures embedded in our CacheOpArgs. These IPCStream structs
// must not move once we attach our AutoIPCStream to them. Therefore,
// its important that any arrays containing streams are pre-sized for
// the number of entries we have in order to avoid realloc moving
// things around on us.
if (mOpResult.type() == CacheOpResult::TCacheMatchAllResult) {
CacheMatchAllResult& result = mOpResult.get_CacheMatchAllResult();
result.responseList().SetCapacity(aEntryCount);
@ -345,6 +371,8 @@ AutoParentOpResult::~AutoParentOpResult() {
QM_WARNONLY_TRY(
OkIf(PCacheStreamControlParent::Send__delete__(mStreamControl)));
}
mStreamCleanupList.Clear();
}
void AutoParentOpResult::Add(CacheId aOpenedCacheId,
@ -372,6 +400,10 @@ void AutoParentOpResult::Add(const SavedResponse& aSavedResponse,
}
case CacheOpResult::TCacheMatchAllResult: {
CacheMatchAllResult& result = mOpResult.get_CacheMatchAllResult();
// Ensure that we don't realloc the array since this can result
// in our AutoIPCStream objects to reference the wrong memory
// location. This should never happen and is a UAF if it does.
// Therefore make this a release assertion.
MOZ_RELEASE_ASSERT(result.responseList().Length() <
result.responseList().Capacity());
result.responseList().AppendElement(aSavedResponse.mValue);
@ -399,6 +431,10 @@ void AutoParentOpResult::Add(const SavedRequest& aSavedRequest,
switch (mOpResult.type()) {
case CacheOpResult::TCacheKeysResult: {
CacheKeysResult& result = mOpResult.get_CacheKeysResult();
// Ensure that we don't realloc the array since this can result
// in our AutoIPCStream objects to reference the wrong memory
// location. This should never happen and is a UAF if it does.
// Therefore make this a release assertion.
MOZ_RELEASE_ASSERT(result.requestList().Length() <
result.requestList().Capacity());
result.requestList().AppendElement(aSavedRequest.mValue);
@ -422,6 +458,9 @@ void AutoParentOpResult::Add(const SavedRequest& aSavedRequest,
const CacheOpResult& AutoParentOpResult::SendAsOpResult() {
MOZ_DIAGNOSTIC_ASSERT(!mSent);
mSent = true;
for (UniquePtr<AutoIPCStream>& autoStream : mStreamCleanupList) {
autoStream->TakeOptionalValue();
}
return mOpResult;
}
@ -466,7 +505,7 @@ void AutoParentOpResult::SerializeReadStream(const nsID& aId,
RefPtr<ReadStream> readStream =
ReadStream::Create(mStreamControl, aId, stream);
ErrorResult rv;
readStream->Serialize(aReadStreamOut, rv);
readStream->Serialize(aReadStreamOut, mStreamCleanupList, rv);
MOZ_DIAGNOSTIC_ASSERT(!rv.Failed());
}

3
dom/cache/AutoUtils.h поставляемый
Просмотреть файл

@ -22,6 +22,7 @@ class ErrorResult;
namespace ipc {
class PBackgroundParent;
class AutoIPCStream;
} // namespace ipc
namespace dom {
@ -64,6 +65,7 @@ class MOZ_STACK_CLASS AutoChildOpArgs final {
private:
TypeUtils* mTypeUtils;
CacheOpArgs mOpArgs;
nsTArray<UniquePtr<mozilla::ipc::AutoIPCStream>> mStreamCleanupList;
bool mSent;
};
@ -90,6 +92,7 @@ class MOZ_STACK_CLASS AutoParentOpResult final {
mozilla::ipc::PBackgroundParent* mManager;
CacheOpResult mOpResult;
CacheStreamControlParent* mStreamControl;
nsTArray<UniquePtr<mozilla::ipc::AutoIPCStream>> mStreamCleanupList;
bool mSent;
};

6
dom/cache/CacheOpParent.cpp поставляемый
Просмотреть файл

@ -12,11 +12,13 @@
#include "mozilla/dom/cache/ManagerId.h"
#include "mozilla/dom/cache/ReadStream.h"
#include "mozilla/dom/cache/SavedTypes.h"
#include "mozilla/ipc/FileDescriptorSetParent.h"
#include "mozilla/ipc/InputStreamUtils.h"
#include "mozilla/ipc/IPCStreamUtils.h"
namespace mozilla::dom::cache {
using mozilla::ipc::FileDescriptorSetParent;
using mozilla::ipc::PBackgroundParent;
CacheOpParent::CacheOpParent(PBackgroundParent* aIpcManager, CacheId aCacheId,
@ -210,8 +212,8 @@ already_AddRefed<nsIInputStream> CacheOpParent::DeserializeCacheStream(
}
// Option 2: A stream was serialized using normal methods or passed
// as a DataPipe. Use the standard method for extracting the
// resulting stream.
// as a PChildToParentStream actor. Use the standard method for
// extracting the resulting stream.
return DeserializeIPCStream(readStream.stream());
}

17
dom/cache/CacheStreamControlChild.cpp поставляемый
Просмотреть файл

@ -11,13 +11,19 @@
#include "mozilla/dom/cache/CacheTypes.h"
#include "mozilla/dom/cache/CacheWorkerRef.h"
#include "mozilla/dom/cache/ReadStream.h"
#include "mozilla/ipc/FileDescriptorSetChild.h"
#include "mozilla/ipc/IPCStreamUtils.h"
#include "mozilla/ipc/PBackgroundChild.h"
#include "mozilla/ipc/PFileDescriptorSetChild.h"
#include "nsISupportsImpl.h"
namespace mozilla::dom::cache {
using mozilla::dom::OptionalFileDescriptorSet;
using mozilla::ipc::AutoIPCStream;
using mozilla::ipc::FileDescriptor;
using mozilla::ipc::FileDescriptorSetChild;
using mozilla::ipc::PFileDescriptorSetChild;
// declared in ActorUtils.h
already_AddRefed<PCacheStreamControlChild> AllocPCacheStreamControlChild() {
@ -72,12 +78,15 @@ void CacheStreamControlChild::SerializeControl(
aReadStreamOut->controlChild() = this;
}
void CacheStreamControlChild::SerializeStream(CacheReadStream* aReadStreamOut,
nsIInputStream* aStream) {
void CacheStreamControlChild::SerializeStream(
CacheReadStream* aReadStreamOut, nsIInputStream* aStream,
nsTArray<UniquePtr<AutoIPCStream>>& aStreamCleanupList) {
NS_ASSERT_OWNINGTHREAD(CacheStreamControlChild);
MOZ_DIAGNOSTIC_ASSERT(aReadStreamOut);
MOZ_ALWAYS_TRUE(mozilla::ipc::SerializeIPCStream(
do_AddRef(aStream), aReadStreamOut->stream(), /* aAllowLazy */ false));
UniquePtr<AutoIPCStream> autoStream(
new AutoIPCStream(aReadStreamOut->stream()));
autoStream->Serialize(aStream, Manager());
aStreamCleanupList.AppendElement(std::move(autoStream));
}
void CacheStreamControlChild::OpenStream(const nsID& aId,

13
dom/cache/CacheStreamControlChild.h поставляемый
Просмотреть файл

@ -12,7 +12,11 @@
#include "mozilla/dom/cache/StreamControl.h"
#include "nsTObserverArray.h"
namespace mozilla::dom::cache {
namespace mozilla {
namespace ipc {
class AutoIPCStream;
} // namespace ipc
namespace dom::cache {
class ReadStream;
@ -31,7 +35,9 @@ class CacheStreamControlChild final : public PCacheStreamControlChild,
virtual void SerializeControl(CacheReadStream* aReadStreamOut) override;
virtual void SerializeStream(CacheReadStream* aReadStreamOut,
nsIInputStream* aStream) override;
nsIInputStream* aStream,
nsTArray<UniquePtr<mozilla::ipc::AutoIPCStream>>&
aStreamCleanupList) override;
virtual void OpenStream(const nsID& aId,
InputStreamResolver&& aResolver) override;
@ -55,6 +61,7 @@ class CacheStreamControlChild final : public PCacheStreamControlChild,
bool mDestroyDelayed;
};
} // namespace mozilla::dom::cache
} // namespace dom::cache
} // namespace mozilla
#endif // mozilla_dom_cache_CacheStreamControlChild_h

26
dom/cache/CacheStreamControlParent.cpp поставляемый
Просмотреть файл

@ -11,14 +11,20 @@
#include "mozilla/dom/cache/CacheTypes.h"
#include "mozilla/dom/cache/ReadStream.h"
#include "mozilla/dom/cache/StreamList.h"
#include "mozilla/ipc/FileDescriptorSetParent.h"
#include "mozilla/ipc/IPCStreamUtils.h"
#include "mozilla/ipc/PBackgroundParent.h"
#include "mozilla/ipc/PFileDescriptorSetParent.h"
#include "nsISupportsImpl.h"
#include "nsTArray.h"
namespace mozilla::dom::cache {
using mozilla::dom::OptionalFileDescriptorSet;
using mozilla::ipc::AutoIPCStream;
using mozilla::ipc::FileDescriptor;
using mozilla::ipc::FileDescriptorSetParent;
using mozilla::ipc::PFileDescriptorSetParent;
// declared in ActorUtils.h
void DeallocPCacheStreamControlParent(PCacheStreamControlParent* aActor) {
@ -43,14 +49,18 @@ void CacheStreamControlParent::SerializeControl(
aReadStreamOut->controlParent() = this;
}
void CacheStreamControlParent::SerializeStream(CacheReadStream* aReadStreamOut,
nsIInputStream* aStream) {
void CacheStreamControlParent::SerializeStream(
CacheReadStream* aReadStreamOut, nsIInputStream* aStream,
nsTArray<UniquePtr<AutoIPCStream>>& aStreamCleanupList) {
NS_ASSERT_OWNINGTHREAD(CacheStreamControlParent);
MOZ_DIAGNOSTIC_ASSERT(aReadStreamOut);
DebugOnly<bool> ok = mozilla::ipc::SerializeIPCStream(
do_AddRef(aStream), aReadStreamOut->stream(), /* aAllowLazy */ false);
UniquePtr<AutoIPCStream> autoStream(
new AutoIPCStream(aReadStreamOut->stream()));
DebugOnly<bool> ok = autoStream->Serialize(aStream, Manager());
MOZ_ASSERT(ok);
aStreamCleanupList.AppendElement(std::move(autoStream));
}
void CacheStreamControlParent::OpenStream(const nsID& aId,
@ -115,11 +125,9 @@ mozilla::ipc::IPCResult CacheStreamControlParent::RecvOpenStream(
OpenStream(aStreamId, [aResolver, self = RefPtr{this}](
nsCOMPtr<nsIInputStream>&& aStream) {
Maybe<IPCStream> stream;
if (self->CanSend() &&
mozilla::ipc::SerializeIPCStream(aStream.forget(), stream,
/* aAllowLazy */ false)) {
aResolver(stream);
AutoIPCStream autoStream;
if (self->CanSend() && autoStream.Serialize(aStream, self->Manager())) {
aResolver(autoStream.TakeOptionalValue());
} else {
aResolver(Nothing());
}

13
dom/cache/CacheStreamControlParent.h поставляемый
Просмотреть файл

@ -12,7 +12,11 @@
#include "mozilla/dom/cache/StreamControl.h"
#include "nsTObserverArray.h"
namespace mozilla::dom::cache {
namespace mozilla {
namespace ipc {
class AutoIPCStream;
} // namespace ipc
namespace dom::cache {
class ReadStream;
class StreamList;
@ -33,7 +37,9 @@ class CacheStreamControlParent final : public PCacheStreamControlParent,
virtual void SerializeControl(CacheReadStream* aReadStreamOut) override;
virtual void SerializeStream(CacheReadStream* aReadStreamOut,
nsIInputStream* aStream) override;
nsIInputStream* aStream,
nsTArray<UniquePtr<mozilla::ipc::AutoIPCStream>>&
aStreamCleanupList) override;
virtual void OpenStream(const nsID& aId,
InputStreamResolver&& aResolver) override;
@ -67,6 +73,7 @@ class CacheStreamControlParent final : public PCacheStreamControlParent,
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CacheStreamControlParent, override)
};
} // namespace mozilla::dom::cache
} // namespace dom::cache
} // namespace mozilla
#endif // mozilla_dom_cache_CacheStreamControlParent_h

1
dom/cache/CacheTypes.ipdlh поставляемый
Просмотреть файл

@ -4,6 +4,7 @@
include protocol PCache;
include protocol PCacheStreamControl;
include protocol PChildToParentStream;
include IPCStream;
include IPCChannelInfo;
include PBackgroundSharedTypes;

3
dom/cache/PCache.ipdl поставляемый
Просмотреть файл

@ -5,6 +5,9 @@
include protocol PBackground;
include protocol PCacheOp;
include protocol PCacheStreamControl;
include protocol PFileDescriptorSet;
include protocol PChildToParentStream;
include protocol PParentToChildStream;
include CacheTypes;

3
dom/cache/PCacheOp.ipdl поставляемый
Просмотреть файл

@ -5,6 +5,9 @@
include protocol PCache;
include protocol PCacheStorage;
include protocol PCacheStreamControl;
include protocol PFileDescriptorSet;
include protocol PChildToParentStream;
include protocol PParentToChildStream;
include CacheTypes;

3
dom/cache/PCacheStorage.ipdl поставляемый
Просмотреть файл

@ -6,6 +6,9 @@ include protocol PBackground;
include protocol PCache;
include protocol PCacheOp;
include protocol PCacheStreamControl;
include protocol PFileDescriptorSet;
include protocol PChildToParentStream;
include protocol PParentToChildStream;
include CacheTypes;

3
dom/cache/PCacheStreamControl.ipdl поставляемый
Просмотреть файл

@ -3,6 +3,9 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
include protocol PBackground;
include protocol PFileDescriptorSet;
include protocol PChildToParentStream;
include protocol PParentToChildStream;
include IPCStream;
using struct nsID from "nsID.h";

54
dom/cache/ReadStream.cpp поставляемый
Просмотреть файл

@ -20,6 +20,7 @@
namespace mozilla::dom::cache {
using mozilla::Unused;
using mozilla::ipc::AutoIPCStream;
using mozilla::ipc::IPCStream;
// ----------------------------------------------------------------------------
@ -31,9 +32,13 @@ class ReadStream::Inner final : public ReadStream::Controllable {
public:
Inner(StreamControl* aControl, const nsID& aId, nsIInputStream* aStream);
void Serialize(Maybe<CacheReadStream>* aReadStreamOut, ErrorResult& aRv);
void Serialize(Maybe<CacheReadStream>* aReadStreamOut,
nsTArray<UniquePtr<AutoIPCStream>>& aStreamCleanupList,
ErrorResult& aRv);
void Serialize(CacheReadStream* aReadStreamOut, ErrorResult& aRv);
void Serialize(CacheReadStream* aReadStreamOut,
nsTArray<UniquePtr<AutoIPCStream>>& aStreamCleanupList,
ErrorResult& aRv);
// ReadStream::Controllable methods
virtual void CloseStream() override;
@ -186,16 +191,18 @@ ReadStream::Inner::Inner(StreamControl* aControl, const nsID& aId,
mControl->AddReadStream(SafeRefPtrFromThis());
}
void ReadStream::Inner::Serialize(Maybe<CacheReadStream>* aReadStreamOut,
ErrorResult& aRv) {
void ReadStream::Inner::Serialize(
Maybe<CacheReadStream>* aReadStreamOut,
nsTArray<UniquePtr<AutoIPCStream>>& aStreamCleanupList, ErrorResult& aRv) {
MOZ_ASSERT(mOwningEventTarget->IsOnCurrentThread());
MOZ_DIAGNOSTIC_ASSERT(aReadStreamOut);
aReadStreamOut->emplace(CacheReadStream());
Serialize(&aReadStreamOut->ref(), aRv);
Serialize(&aReadStreamOut->ref(), aStreamCleanupList, aRv);
}
void ReadStream::Inner::Serialize(CacheReadStream* aReadStreamOut,
ErrorResult& aRv) {
void ReadStream::Inner::Serialize(
CacheReadStream* aReadStreamOut,
nsTArray<UniquePtr<AutoIPCStream>>& aStreamCleanupList, ErrorResult& aRv) {
MOZ_ASSERT(mOwningEventTarget->IsOnCurrentThread());
MOZ_DIAGNOSTIC_ASSERT(aReadStreamOut);
@ -212,12 +219,15 @@ void ReadStream::Inner::Serialize(CacheReadStream* aReadStreamOut,
{
MutexAutoLock lock(mMutex);
mControl->SerializeStream(aReadStreamOut, mStream);
mControl->SerializeStream(aReadStreamOut, mStream, aStreamCleanupList);
}
MOZ_DIAGNOSTIC_ASSERT(aReadStreamOut->stream().isNothing() ||
aReadStreamOut->stream().ref().stream().type() !=
mozilla::ipc::InputStreamParams::T__None);
MOZ_DIAGNOSTIC_ASSERT(
aReadStreamOut->stream().isNothing() ||
(aReadStreamOut->stream().ref().stream().type() !=
mozilla::ipc::InputStreamParams::TIPCRemoteStreamParams &&
aReadStreamOut->stream().ref().stream().type() !=
mozilla::ipc::InputStreamParams::T__None));
// We're passing ownership across the IPC barrier with the control, so
// do not signal that the stream is closed here.
@ -505,9 +515,12 @@ already_AddRefed<ReadStream> ReadStream::Create(
return nullptr;
}
MOZ_DIAGNOSTIC_ASSERT(aReadStream.stream().isNothing() ||
aReadStream.stream().ref().stream().type() !=
mozilla::ipc::InputStreamParams::T__None);
MOZ_DIAGNOSTIC_ASSERT(
aReadStream.stream().isNothing() ||
(aReadStream.stream().ref().stream().type() !=
mozilla::ipc::InputStreamParams::TIPCRemoteStreamParams &&
aReadStream.stream().ref().stream().type() !=
mozilla::ipc::InputStreamParams::T__None));
// Control is guaranteed to survive this method as ActorDestroy() cannot
// run on this thread until we complete.
@ -547,13 +560,16 @@ already_AddRefed<ReadStream> ReadStream::Create(
static_cast<CacheStreamControlParent*>(aControl), aId, aStream));
}
void ReadStream::Serialize(Maybe<CacheReadStream>* aReadStreamOut,
ErrorResult& aRv) {
mInner->Serialize(aReadStreamOut, aRv);
void ReadStream::Serialize(
Maybe<CacheReadStream>* aReadStreamOut,
nsTArray<UniquePtr<AutoIPCStream>>& aStreamCleanupList, ErrorResult& aRv) {
mInner->Serialize(aReadStreamOut, aStreamCleanupList, aRv);
}
void ReadStream::Serialize(CacheReadStream* aReadStreamOut, ErrorResult& aRv) {
mInner->Serialize(aReadStreamOut, aRv);
void ReadStream::Serialize(
CacheReadStream* aReadStreamOut,
nsTArray<UniquePtr<AutoIPCStream>>& aStreamCleanupList, ErrorResult& aRv) {
mInner->Serialize(aReadStreamOut, aStreamCleanupList, aRv);
}
ReadStream::ReadStream(SafeRefPtr<ReadStream::Inner> aInner)

13
dom/cache/ReadStream.h поставляемый
Просмотреть файл

@ -19,6 +19,9 @@
namespace mozilla {
class ErrorResult;
namespace ipc {
class AutoIPCStream;
} // namespace ipc
namespace dom::cache {
class CacheReadStream;
@ -74,8 +77,14 @@ class ReadStream final : public nsIInputStream {
PCacheStreamControlParent* aControl, const nsID& aId,
nsIInputStream* aStream);
void Serialize(Maybe<CacheReadStream>* aReadStreamOut, ErrorResult& aRv);
void Serialize(CacheReadStream* aReadStreamOut, ErrorResult& aRv);
void Serialize(
Maybe<CacheReadStream>* aReadStreamOut,
nsTArray<UniquePtr<mozilla::ipc::AutoIPCStream>>& aStreamCleanupList,
ErrorResult& aRv);
void Serialize(
CacheReadStream* aReadStreamOut,
nsTArray<UniquePtr<mozilla::ipc::AutoIPCStream>>& aStreamCleanupList,
ErrorResult& aRv);
private:
class Inner;

14
dom/cache/StreamControl.h поставляемый
Просмотреть файл

@ -14,7 +14,11 @@
struct nsID;
namespace mozilla::dom::cache {
namespace mozilla {
namespace ipc {
class AutoIPCStream;
} // namespace ipc
namespace dom::cache {
class CacheReadStream;
@ -26,8 +30,9 @@ class StreamControl {
// abstract interface that must be implemented by child class
virtual void SerializeControl(CacheReadStream* aReadStreamOut) = 0;
virtual void SerializeStream(CacheReadStream* aReadStreamOut,
nsIInputStream* aStream) = 0;
virtual void SerializeStream(
CacheReadStream* aReadStreamOut, nsIInputStream* aStream,
nsTArray<UniquePtr<mozilla::ipc::AutoIPCStream>>& aStreamCleanupList) = 0;
virtual void OpenStream(const nsID& aId, InputStreamResolver&& aResolver) = 0;
@ -70,6 +75,7 @@ class StreamControl {
ReadStreamList mReadStreamList;
};
} // namespace mozilla::dom::cache
} // namespace dom::cache
} // namespace mozilla
#endif // mozilla_dom_cache_StreamControl_h

34
dom/cache/TypeUtils.cpp поставляемый
Просмотреть файл

@ -20,6 +20,7 @@
#include "mozilla/ipc/BackgroundChild.h"
#include "mozilla/ipc/IPCStreamUtils.h"
#include "mozilla/ipc/PBackgroundChild.h"
#include "mozilla/ipc/PFileDescriptorSetChild.h"
#include "mozilla/ipc/InputStreamUtils.h"
#include "nsCharSeparatedTokenizer.h"
#include "nsCOMPtr.h"
@ -33,9 +34,11 @@
namespace mozilla::dom::cache {
using mozilla::ipc::AutoIPCStream;
using mozilla::ipc::BackgroundChild;
using mozilla::ipc::FileDescriptor;
using mozilla::ipc::PBackgroundChild;
using mozilla::ipc::PFileDescriptorSetChild;
namespace {
@ -110,9 +113,10 @@ SafeRefPtr<InternalRequest> TypeUtils::ToInternalRequest(
return ToInternalRequest(aIn.GetAsUSVString(), aRv);
}
void TypeUtils::ToCacheRequest(CacheRequest& aOut, const InternalRequest& aIn,
BodyAction aBodyAction,
SchemeAction aSchemeAction, ErrorResult& aRv) {
void TypeUtils::ToCacheRequest(
CacheRequest& aOut, const InternalRequest& aIn, BodyAction aBodyAction,
SchemeAction aSchemeAction,
nsTArray<UniquePtr<AutoIPCStream>>& aStreamCleanupList, ErrorResult& aRv) {
aIn.GetMethod(aOut.method());
nsCString url(aIn.GetURLWithoutFragment());
bool schemeValid;
@ -157,7 +161,7 @@ void TypeUtils::ToCacheRequest(CacheRequest& aOut, const InternalRequest& aIn,
nsCOMPtr<nsIInputStream> stream;
aIn.GetBody(getter_AddRefs(stream));
SerializeCacheStream(stream, &aOut.body(), aRv);
SerializeCacheStream(stream, &aOut.body(), aStreamCleanupList, aRv);
if (NS_WARN_IF(aRv.Failed())) {
return;
}
@ -200,8 +204,9 @@ void TypeUtils::ToCacheResponseWithoutBody(CacheResponse& aOut,
aOut.paddingSize() = aIn.GetPaddingSize();
}
void TypeUtils::ToCacheResponse(JSContext* aCx, CacheResponse& aOut,
Response& aIn, ErrorResult& aRv) {
void TypeUtils::ToCacheResponse(
JSContext* aCx, CacheResponse& aOut, Response& aIn,
nsTArray<UniquePtr<AutoIPCStream>>& aStreamCleanupList, ErrorResult& aRv) {
bool bodyUsed = aIn.GetBodyUsed(aRv);
if (NS_WARN_IF(aRv.Failed())) {
return;
@ -226,7 +231,7 @@ void TypeUtils::ToCacheResponse(JSContext* aCx, CacheResponse& aOut,
}
}
SerializeCacheStream(stream, &aOut.body(), aRv);
SerializeCacheStream(stream, &aOut.body(), aStreamCleanupList, aRv);
if (NS_WARN_IF(aRv.Failed())) {
return;
}
@ -479,9 +484,9 @@ SafeRefPtr<InternalRequest> TypeUtils::ToInternalRequest(const nsAString& aIn,
return request->GetInternalRequest();
}
void TypeUtils::SerializeCacheStream(nsIInputStream* aStream,
Maybe<CacheReadStream>* aStreamOut,
ErrorResult& aRv) {
void TypeUtils::SerializeCacheStream(
nsIInputStream* aStream, Maybe<CacheReadStream>* aStreamOut,
nsTArray<UniquePtr<AutoIPCStream>>& aStreamCleanupList, ErrorResult& aRv) {
*aStreamOut = Nothing();
if (!aStream) {
return;
@ -489,7 +494,7 @@ void TypeUtils::SerializeCacheStream(nsIInputStream* aStream,
RefPtr<ReadStream> controlled = do_QueryObject(aStream);
if (controlled) {
controlled->Serialize(aStreamOut, aRv);
controlled->Serialize(aStreamOut, aStreamCleanupList, aRv);
return;
}
@ -499,9 +504,10 @@ void TypeUtils::SerializeCacheStream(nsIInputStream* aStream,
cacheStream.controlChild() = nullptr;
cacheStream.controlParent() = nullptr;
MOZ_ALWAYS_TRUE(mozilla::ipc::SerializeIPCStream(do_AddRef(aStream),
cacheStream.stream(),
/* aAllowLazy */ false));
UniquePtr<AutoIPCStream> autoStream(new AutoIPCStream(cacheStream.stream()));
autoStream->Serialize(aStream, GetIPCManager());
aStreamCleanupList.AppendElement(std::move(autoStream));
}
} // namespace mozilla::dom::cache

22
dom/cache/TypeUtils.h поставляемый
Просмотреть файл

@ -21,6 +21,7 @@ namespace mozilla {
namespace ipc {
class PBackgroundChild;
class AutoIPCStream;
} // namespace ipc
namespace dom {
@ -72,15 +73,19 @@ class TypeUtils {
JSContext* aCx, const OwningRequestOrUSVString& aIn,
BodyAction aBodyAction, ErrorResult& aRv);
void ToCacheRequest(CacheRequest& aOut, const InternalRequest& aIn,
BodyAction aBodyAction, SchemeAction aSchemeAction,
ErrorResult& aRv);
void ToCacheRequest(
CacheRequest& aOut, const InternalRequest& aIn, BodyAction aBodyAction,
SchemeAction aSchemeAction,
nsTArray<UniquePtr<mozilla::ipc::AutoIPCStream>>& aStreamCleanupList,
ErrorResult& aRv);
void ToCacheResponseWithoutBody(CacheResponse& aOut, InternalResponse& aIn,
ErrorResult& aRv);
void ToCacheResponse(JSContext* aCx, CacheResponse& aOut, Response& aIn,
ErrorResult& aRv);
void ToCacheResponse(
JSContext* aCx, CacheResponse& aOut, Response& aIn,
nsTArray<UniquePtr<mozilla::ipc::AutoIPCStream>>& aStreamCleanupList,
ErrorResult& aRv);
void ToCacheQueryParams(CacheQueryParams& aOut, const CacheQueryOptions& aIn);
@ -123,9 +128,10 @@ class TypeUtils {
SafeRefPtr<InternalRequest> ToInternalRequest(const nsAString& aIn,
ErrorResult& aRv);
void SerializeCacheStream(nsIInputStream* aStream,
Maybe<CacheReadStream>* aStreamOut,
ErrorResult& aRv);
void SerializeCacheStream(
nsIInputStream* aStream, Maybe<CacheReadStream>* aStreamOut,
nsTArray<UniquePtr<mozilla::ipc::AutoIPCStream>>& aStreamCleanupList,
ErrorResult& aRv);
void SerializeSendStream(nsIInputStream* aStream,
CacheReadStream& aReadStreamOut, ErrorResult& aRv);

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

@ -4,6 +4,10 @@
include protocol PClientManager;
include protocol PClientSourceOp;
include protocol PChildToParentStream;
include protocol PParentToChildStream;
include protocol PFileDescriptorSet;
include protocol PRemoteLazyInputStream;
include ClientIPCTypes;
namespace mozilla {

Просмотреть файл

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

Просмотреть файл

@ -7,6 +7,8 @@ include IPCChannelInfo;
include PBackgroundSharedTypes;
include PerformanceTimingTypes;
include protocol PRemoteLazyInputStream;
include "mozilla/dom/FetchIPCTypes.h";
using HeadersGuardEnum from "mozilla/dom/HeadersBinding.h";
@ -17,7 +19,6 @@ 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 {
@ -33,7 +34,7 @@ struct ParentToParentStream {
};
struct ParentToChildStream {
RemoteLazyInputStream stream;
PRemoteLazyInputStream actor;
};
struct ChildToParentStream {

Просмотреть файл

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

Просмотреть файл

@ -134,7 +134,9 @@ InternalResponseMetadata InternalResponse::GetMetadata() {
void InternalResponse::ToChildToParentInternalResponse(
ChildToParentInternalResponse* aIPCResponse,
mozilla::ipc::PBackgroundChild* aManager) {
mozilla::ipc::PBackgroundChild* aManager,
UniquePtr<mozilla::ipc::AutoIPCStream>& aAutoBodyStream,
UniquePtr<mozilla::ipc::AutoIPCStream>& aAutoAlternativeBodyStream) {
*aIPCResponse = ChildToParentInternalResponse(GetMetadata(), Nothing(),
UNKNOWN_BODY_SIZE, Nothing());
@ -146,8 +148,9 @@ void InternalResponse::ToChildToParentInternalResponse(
aIPCResponse->body().emplace(ChildToParentStream());
aIPCResponse->bodySize() = bodySize;
DebugOnly<bool> ok = mozilla::ipc::SerializeIPCStream(
body.forget(), aIPCResponse->body()->stream(), /* aAllowLazy */ false);
aAutoBodyStream.reset(
new mozilla::ipc::AutoIPCStream(aIPCResponse->body()->stream()));
DebugOnly<bool> ok = aAutoBodyStream->Serialize(body, aManager);
MOZ_ASSERT(ok);
}
@ -155,9 +158,10 @@ void InternalResponse::ToChildToParentInternalResponse(
if (alternativeBody) {
aIPCResponse->alternativeBody().emplace(ChildToParentStream());
DebugOnly<bool> ok = mozilla::ipc::SerializeIPCStream(
alternativeBody.forget(), aIPCResponse->alternativeBody()->stream(),
/* aAllowLazy */ false);
aAutoAlternativeBodyStream.reset(new mozilla::ipc::AutoIPCStream(
aIPCResponse->alternativeBody()->stream()));
DebugOnly<bool> ok =
aAutoAlternativeBodyStream->Serialize(alternativeBody, aManager);
MOZ_ASSERT(ok);
}
}

Просмотреть файл

@ -23,6 +23,7 @@
namespace mozilla {
namespace ipc {
class AutoIPCStream;
class PBackgroundChild;
class PBackgroundParent;
class PrincipalInfo;
@ -51,9 +52,12 @@ class InternalResponse final : public AtomicSafeRefCounted<InternalResponse> {
static SafeRefPtr<InternalResponse> FromIPC(
const ParentToParentInternalResponse& aIPCResponse);
// Note: the AutoIPCStreams must outlive the ChildToParentInternalResponse.
void ToChildToParentInternalResponse(
ChildToParentInternalResponse* aIPCResponse,
mozilla::ipc::PBackgroundChild* aManager);
mozilla::ipc::PBackgroundChild* aManager,
UniquePtr<mozilla::ipc::AutoIPCStream>& aAutoBodyStream,
UniquePtr<mozilla::ipc::AutoIPCStream>& aAutoAlternativeBodyStream);
ParentToParentInternalResponse ToParentToParentInternalResponse();

Просмотреть файл

@ -50,12 +50,22 @@ class TemporaryFileInputStream final : public nsFileInputStream {
return NS_OK;
}
void Serialize(InputStreamParams& aParams, uint32_t aMaxSize,
uint32_t* aSizeUsed) override {
void Serialize(InputStreamParams& aParams,
FileDescriptorArray& aFileDescriptors, bool aDelayedStart,
uint32_t aMaxSize, uint32_t* aSizeUsed,
ParentToChildStreamActorManager* aManager) override {
MOZ_CRASH("This inputStream cannot be serialized.");
}
bool Deserialize(const InputStreamParams& aParams) override {
void Serialize(InputStreamParams& aParams,
FileDescriptorArray& aFileDescriptors, bool aDelayedStart,
uint32_t aMaxSize, uint32_t* aSizeUsed,
ChildToParentStreamActorManager* aManager) override {
MOZ_CRASH("This inputStream cannot be serialized.");
}
bool Deserialize(const InputStreamParams& aParams,
const FileDescriptorArray& aFileDescriptors) override {
MOZ_CRASH("This inputStream cannot be deserialized.");
return false;
}

Просмотреть файл

@ -0,0 +1,22 @@
/* 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 PFileDescriptorSet;
include "mozilla/ipc/ProtocolMessageUtils.h";
using struct mozilla::void_t from "mozilla/ipc/IPCCore.h";
namespace mozilla {
namespace dom {
union OptionalFileDescriptorSet
{
PFileDescriptorSet;
FileDescriptor[];
void_t;
};
}
}

Просмотреть файл

@ -2,11 +2,14 @@
* 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 PChildToParentStream;
include protocol PParentToChildStream;
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 {
@ -14,7 +17,7 @@ union RemoteLazyStream
{
// Parent to Child: The child will receive a RemoteLazyInputStream. Nothing
// can be done with it except retrieving the size.
RemoteLazyInputStream;
PRemoteLazyInputStream;
// Child to Parent: Normal serialization.
IPCStream;

Просмотреть файл

@ -8,6 +8,7 @@
#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"
@ -33,8 +34,11 @@ 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::TRemoteLazyInputStream: {
inputStream = stream.get_RemoteLazyInputStream();
case RemoteLazyStream::TPRemoteLazyInputStreamChild: {
RemoteLazyInputStreamChild* actor =
static_cast<RemoteLazyInputStreamChild*>(
stream.get_PRemoteLazyInputStreamChild());
inputStream = actor->CreateStream();
break;
}
@ -125,22 +129,13 @@ nsresult SerializeInternal(BlobImpl* aBlobImpl, M* aManager,
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;
RemoteLazyStream stream;
rv = RemoteLazyInputStreamUtils::SerializeInputStream(
inputStream, aIPCBlob.size(), stream, aManager);
if (NS_WARN_IF(rv.Failed())) {
return rv.StealNSResult();
}
IPCStream stream;
if (!mozilla::ipc::SerializeIPCStream(inputStream.forget(), stream,
/* aAllowLazy */ true)) {
return NS_ERROR_FAILURE;
}
aIPCBlob.inputStream() = stream;
return NS_OK;
}

Просмотреть файл

@ -66,10 +66,11 @@
* and its size is lower than 1Mb, we are able to recreate the stream completely
* on the parent side. This happens, basically with any kind of child-to-parent
* stream except for huge memory streams. In this case we end up using
* DataPipe. See more information in IPCStreamUtils.h.
* PChildToParentStream. See more information in IPCStreamUtils.h.
*
* In order to populate IPCStream correctly, we use SerializeIPCStream as
* documented in IPCStreamUtils.h.
* In order to populate IPCStream correctly, we use AutoIPCStream as documented
* in IPCStreamUtils.h. Note that we use the 'delayed start' feature because,
* often, the stream doesn't need to be read on the parent side.
*
* Parent to Child Blob Serialization
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Просмотреть файл

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

Просмотреть файл

@ -2,20 +2,45 @@
* 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 PChildToParentStream;
include protocol PContent;
include protocol PFileDescriptorSet;
include protocol PParentToChildStream;
include protocol PSocketProcess;
include IPCStream;
namespace mozilla {
protocol PRemoteLazyInputStream
{
manager PBackground or PContent or PSocketProcess;
parent:
async Clone(Endpoint<PRemoteLazyInputStreamParent> aCloneEndpoint);
async StreamNeeded();
async StreamNeeded(uint64_t aStart, uint64_t aLength) returns (IPCStream? stream);
async LengthNeeded();
async LengthNeeded() returns (int64_t length);
// When this is called, the parent releases the inputStream and sends a
// __delete__.
async Close();
async Goodbye();
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__();
};
} // namespace mozilla

Просмотреть файл

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

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -7,7 +7,6 @@
#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"
@ -42,56 +41,34 @@ class RemoteLazyInputStream final : public nsIAsyncInputStream,
NS_DECL_NSIINPUTSTREAMLENGTH
NS_DECL_NSIASYNCINPUTSTREAMLENGTH
// 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);
explicit RemoteLazyInputStream(RemoteLazyInputStreamChild* aActor);
void StreamReady(already_AddRefed<nsIInputStream> aInputStream);
void LengthReady(int64_t aLength);
// mozIRemoteLazyInputStream
NS_IMETHOD TakeInternalStream(nsIInputStream** aStream) override;
NS_IMETHOD GetInternalStreamID(nsID& aID) override;
NS_IMETHOD_(nsIInputStream*) GetInternalStream() override {
if (mRemoteStream) {
return mRemoteStream;
}
if (mAsyncRemoteStream) {
return mAsyncRemoteStream;
}
return nullptr;
}
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();
void StreamNeeded() REQUIRES(mMutex);
nsresult EnsureAsyncRemoteStream(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);
void InitWithExistingRange(uint64_t aStart, uint64_t aLength,
const MutexAutoLock& aProofOfLock);
// 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"};
RefPtr<RemoteLazyInputStreamChild> mActor;
// This is the list of possible states.
enum {
@ -104,49 +81,43 @@ 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 mInnerStream. From now on, any
// method call will be forwared to mInnerStream or mAsyncInnerStream.
// state. The received stream is stored in mRemoteStream. From now on, any
// method call will be forwared to mRemoteStream.
eRunning,
// If Close() or CloseWithStatus() is called, we move to this state.
// mInnerStream is released and any method will return
// mRemoveStream is released and any method will return
// NS_BASE_STREAM_CLOSED.
eClosed,
} mState GUARDED_BY(mMutex) = eClosed;
} mState;
// 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);
uint64_t mStart;
uint64_t mLength;
nsCOMPtr<nsIInputStream> mInnerStream GUARDED_BY(mMutex);
nsCOMPtr<nsIAsyncInputStream> mAsyncInnerStream GUARDED_BY(mMutex);
// Set to true if the stream is used via Read/ReadSegments or Close.
bool mConsumed;
// 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;
nsCOMPtr<nsIInputStream> mRemoteStream;
nsCOMPtr<nsIAsyncInputStream> mAsyncRemoteStream;
// These 2 values are set only if mState is ePending.
nsCOMPtr<nsIFileMetadataCallback> mFileMetadataCallback GUARDED_BY(mMutex);
nsCOMPtr<nsIEventTarget> mFileMetadataCallbackEventTarget GUARDED_BY(mMutex);
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;
};
} // 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

Просмотреть файл

@ -7,44 +7,442 @@
#include "RemoteLazyInputStreamChild.h"
#include "RemoteLazyInputStreamThread.h"
#include "mozilla/ipc/IPCStreamUtils.h"
#include "mozilla/dom/WorkerCommon.h"
#include "mozilla/dom/WorkerRef.h"
namespace mozilla {
extern mozilla::LazyLogModule gRemoteLazyStreamLog;
using namespace dom;
RemoteLazyInputStreamChild::RemoteLazyInputStreamChild(const nsID& aID)
: mID(aID) {}
namespace {
RemoteLazyInputStreamChild::~RemoteLazyInputStreamChild() = default;
// 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) {}
void RemoteLazyInputStreamChild::StreamCreated() {
size_t count = ++mStreamCount;
MOZ_LOG(gRemoteLazyStreamLog, LogLevel::Verbose,
("Child::StreamCreated %s = %zu", nsIDToCString(mID).get(), count));
}
NS_IMETHOD
Run() override {
mActor->Shutdown();
return NS_OK;
}
void RemoteLazyInputStreamChild::StreamConsumed() {
size_t count = --mStreamCount;
MOZ_LOG(gRemoteLazyStreamLog, LogLevel::Verbose,
("Child::StreamConsumed %s = %zu", nsIDToCString(mID).get(), count));
private:
RefPtr<RemoteLazyInputStreamChild> mActor;
};
// 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();
}
}));
// 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);
}
}
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());
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::ActorDestroy(
IProtocol::ActorDestroyReason aReason) {
bool migrating = false;
{
MutexAutoLock lock(mMutex);
migrating = mState == eActiveMigrating;
mState = migrating ? eInactiveMigrating : eInactive;
}
if (!migrating) {
// Let's cleanup the workerRef and the pending operation queue.
Shutdown();
return;
}
}
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();
}
}
}

Просмотреть файл

@ -8,32 +8,97 @@
#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)
explicit RemoteLazyInputStreamChild(const nsID& aID);
RemoteLazyInputStreamChild(const nsID& aID, uint64_t aSize);
const nsID& StreamID() const { return mID; }
void ActorDestroy(IProtocol::ActorDestroyReason aReason) override;
// 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();
ActorState State();
void ActorDestroy(ActorDestroyReason aReason) override;
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();
private:
~RemoteLazyInputStreamChild() override;
const nsID mID;
// 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;
std::atomic<size_t> mStreamCount{0};
// 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;
};
} // namespace mozilla

Просмотреть файл

@ -5,118 +5,257 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "RemoteLazyInputStreamParent.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"
#include "mozilla/InputStreamLengthHelper.h"
#include "RemoteLazyInputStreamStorage.h"
namespace mozilla {
extern mozilla::LazyLogModule gRemoteLazyStreamLog;
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);
RemoteLazyInputStreamParent::RemoteLazyInputStreamParent(const nsID& aID)
: mID(aID) {
auto storage = RemoteLazyInputStreamStorage::Get().unwrapOr(nullptr);
if (storage) {
storage->ActorCreated(mID);
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);
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::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->ActorDestroyed(mID);
storage->ForgetStream(mID);
}
if (callback) {
callback->ActorDestroyed(mID);
}
}
mozilla::ipc::IPCResult RemoteLazyInputStreamParent::RecvClone(
mozilla::ipc::Endpoint<PRemoteLazyInputStreamParent>&& aCloneEndpoint) {
if (!aCloneEndpoint.IsValid()) {
return IPC_FAIL(this, "Unexpected invalid endpoint in RecvClone");
}
void RemoteLazyInputStreamParent::SetCallback(
RemoteLazyInputStreamParentCallback* aCallback) {
MOZ_ASSERT(aCallback);
MOZ_ASSERT(!mCallback);
MOZ_LOG(gRemoteLazyStreamLog, LogLevel::Debug,
("Parent::RecvClone %s", nsIDToCString(mID).get()));
auto* newActor = new RemoteLazyInputStreamParent(mID);
aCloneEndpoint.Bind(newActor);
return IPC_OK();
mCallback = aCallback;
}
mozilla::ipc::IPCResult RemoteLazyInputStreamParent::RecvStreamNeeded(
uint64_t aStart, uint64_t aLength, StreamNeededResolver&& aResolver) {
mozilla::ipc::IPCResult RemoteLazyInputStreamParent::RecvStreamNeeded() {
MOZ_ASSERT(mContentManager || mPBackgroundManager || mSocketProcessManager);
nsCOMPtr<nsIInputStream> stream;
auto storage = RemoteLazyInputStreamStorage::Get().unwrapOr(nullptr);
if (storage) {
storage->GetStream(mID, aStart, aLength, getter_AddRefs(stream));
storage->GetStream(mID, 0, mSize, getter_AddRefs(stream));
}
if (!stream) {
MOZ_LOG(gRemoteLazyStreamLog, LogLevel::Warning,
("Parent::RecvStreamNeeded not available! %s",
nsIDToCString(mID).get()));
aResolver(Nothing());
if (!SendStreamReady(Nothing())) {
return IPC_FAIL(this, "SendStreamReady failed");
}
return IPC_OK();
}
Maybe<IPCStream> ipcStream;
if (NS_WARN_IF(!SerializeIPCStream(stream.forget(), ipcStream,
/* aAllowLazy */ false))) {
return IPC_FAIL(this, "IPCStream serialization failed!");
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");
}
MOZ_LOG(gRemoteLazyStreamLog, LogLevel::Verbose,
("Parent::RecvStreamNeeded resolve %s", nsIDToCString(mID).get()));
aResolver(ipcStream);
return IPC_OK();
}
mozilla::ipc::IPCResult RemoteLazyInputStreamParent::RecvLengthNeeded(
LengthNeededResolver&& aResolver) {
mozilla::ipc::IPCResult RemoteLazyInputStreamParent::RecvLengthNeeded() {
MOZ_ASSERT(mContentManager || mPBackgroundManager || mSocketProcessManager);
nsCOMPtr<nsIInputStream> stream;
auto storage = RemoteLazyInputStreamStorage::Get().unwrapOr(nullptr);
if (storage) {
storage->GetStream(mID, 0, UINT64_MAX, getter_AddRefs(stream));
storage->GetStream(mID, 0, mSize, getter_AddRefs(stream));
}
if (!stream) {
MOZ_LOG(gRemoteLazyStreamLog, LogLevel::Warning,
("Parent::RecvLengthNeeded not available! %s",
nsIDToCString(mID).get()));
aResolver(-1);
if (!SendLengthReady(-1)) {
return IPC_FAIL(this, "SendLengthReady failed");
}
return IPC_OK();
}
int64_t length = -1;
if (InputStreamLengthHelper::GetSyncLength(stream, &length)) {
MOZ_LOG(gRemoteLazyStreamLog, LogLevel::Verbose,
("Parent::RecvLengthNeeded sync resolve %" PRId64 "! %s", length,
nsIDToCString(mID).get()));
aResolver(length);
Unused << SendLengthReady(length);
return IPC_OK();
}
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);
});
RefPtr<RemoteLazyInputStreamParent> self = this;
InputStreamLengthHelper::GetAsyncLength(stream, [self](int64_t aLength) {
if (self->mContentManager || self->mPBackgroundManager ||
self->mSocketProcessManager) {
Unused << self->SendLengthReady(aLength);
}
});
return IPC_OK();
}
mozilla::ipc::IPCResult RemoteLazyInputStreamParent::RecvGoodbye() {
MOZ_LOG(gRemoteLazyStreamLog, LogLevel::Verbose,
("Parent::RecvGoodbye! %s", nsIDToCString(mID).get()));
Close();
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;
return IPC_OK();
}

Просмотреть файл

@ -13,30 +13,96 @@ 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)
explicit RemoteLazyInputStreamParent(const nsID& aID);
// 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);
const nsID& ID() const { return mID; }
static already_AddRefed<RemoteLazyInputStreamParent> Create(
nsIInputStream* aInputStream, uint64_t aSize, uint64_t aChildID,
nsresult* aRv, mozilla::ipc::PBackgroundParent* aManager);
mozilla::ipc::IPCResult RecvClone(
mozilla::ipc::Endpoint<PRemoteLazyInputStreamParent>&& aCloneEndpoint);
static already_AddRefed<RemoteLazyInputStreamParent> Create(
nsIInputStream* aInputStream, uint64_t aSize, uint64_t aChildID,
nsresult* aRv, mozilla::net::SocketProcessParent* aManager);
mozilla::ipc::IPCResult RecvStreamNeeded(uint64_t aStart, uint64_t aLength,
StreamNeededResolver&& aResolver);
static already_AddRefed<RemoteLazyInputStreamParent> Create(
const nsID& aID, uint64_t aSize,
mozilla::ipc::PBackgroundParent* aManager);
mozilla::ipc::IPCResult RecvLengthNeeded(LengthNeededResolver&& aResolver);
mozilla::ipc::IPCResult RecvGoodbye();
static already_AddRefed<RemoteLazyInputStreamParent> Create(
const nsID& aID, uint64_t aSize,
mozilla::net::SocketProcessParent* aManager);
void ActorDestroy(IProtocol::ActorDestroyReason aReason) override;
const nsID& ID() const { return mID; }
uint64_t Size() const { return mSize; }
void SetCallback(RemoteLazyInputStreamParentCallback* aCallback);
mozilla::ipc::IPCResult RecvStreamNeeded();
mozilla::ipc::IPCResult RecvLengthNeeded();
mozilla::ipc::IPCResult RecvClose();
mozilla::ipc::IPCResult Recv__delete__() 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

Просмотреть файл

@ -17,8 +17,6 @@ namespace mozilla {
using namespace hal;
extern mozilla::LazyLogModule gRemoteLazyStreamLog;
namespace {
StaticMutex gMutex;
StaticRefPtr<RemoteLazyInputStreamStorage> gStorage;
@ -51,40 +49,61 @@ 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) {
MOZ_ASSERT(!strcmp(aTopic, "xpcom-shutdown"));
if (!strcmp(aTopic, "xpcom-shutdown")) {
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
if (obs) {
obs->RemoveObserver(this, "xpcom-shutdown");
obs->RemoveObserver(this, "ipc:content-shutdown");
}
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
if (obs) {
obs->RemoveObserver(this, "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;
}
mozilla::StaticMutexAutoLock lock(gMutex);
gStorage = nullptr;
for (auto iter = mStorage.Iter(); !iter.Done(); iter.Next()) {
if (iter.Data()->mChildID == childID) {
iter.Remove();
}
}
return NS_OK;
}
void RemoteLazyInputStreamStorage::AddStream(nsIInputStream* aInputStream,
const nsID& aID) {
const nsID& aID, uint64_t aSize,
uint64_t aChildID) {
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));
@ -92,9 +111,6 @@ 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);
@ -118,11 +134,8 @@ 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
@ -135,6 +148,7 @@ void RemoteLazyInputStreamStorage::GetStream(const nsID& aID, uint64_t aStart,
}
inputStream = data->mInputStream;
size = data->mSize;
}
MOZ_ASSERT(inputStream);
@ -163,7 +177,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 < UINT64_MAX) {
if (aStart > 0 || aLength < size) {
clonedStream =
new SlicedInputStream(clonedStream.forget(), aStart, aLength);
}
@ -175,10 +189,6 @@ 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) {
@ -189,9 +199,6 @@ 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) {
@ -203,41 +210,4 @@ 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

Просмотреть файл

@ -16,15 +16,7 @@ struct nsID;
namespace mozilla {
class NS_NO_VTABLE RemoteLazyInputStreamParentCallback {
public:
virtual void ActorDestroyed(const nsID& aID) = 0;
NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING
protected:
virtual ~RemoteLazyInputStreamParentCallback() = default;
};
class RemoteLazyInputStreamParentCallback;
class RemoteLazyInputStreamStorage final : public nsIObserver {
public:
@ -36,9 +28,8 @@ class RemoteLazyInputStreamStorage final : public nsIObserver {
static Result<RefPtr<RemoteLazyInputStreamStorage>, nsresult> Get();
nsISerialEventTarget* TaskQueue() { return mTaskQueue; }
void AddStream(nsIInputStream* aInputStream, const nsID& aID);
void AddStream(nsIInputStream* aInputStream, const nsID& aID, uint64_t aSize,
uint64_t aChildID);
// Removes and returns the stream corresponding to the nsID. May return a
// nullptr if there's no stream stored for the nsID.
@ -55,19 +46,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;
size_t mActorCount = 0;
// 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;
};
nsClassHashtable<nsIDHashKey, StreamData> mStorage;

Просмотреть файл

@ -38,10 +38,58 @@ 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);
@ -80,6 +128,14 @@ 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());
@ -123,6 +179,31 @@ 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)

Просмотреть файл

@ -25,10 +25,14 @@ 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();
@ -36,7 +40,13 @@ 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();

Просмотреть файл

@ -0,0 +1,119 @@
/* -*- 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

Просмотреть файл

@ -0,0 +1,59 @@
/* -*- 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

Просмотреть файл

@ -27,6 +27,7 @@ EXPORTS.mozilla += [
"RemoteLazyInputStreamParent.h",
"RemoteLazyInputStreamStorage.h",
"RemoteLazyInputStreamThread.h",
"RemoteLazyInputStreamUtils.h",
]
UNIFIED_SOURCES += [
@ -38,11 +39,13 @@ UNIFIED_SOURCES += [
"RemoteLazyInputStreamParent.cpp",
"RemoteLazyInputStreamStorage.cpp",
"RemoteLazyInputStreamThread.cpp",
"RemoteLazyInputStreamUtils.cpp",
"TemporaryIPCBlobChild.cpp",
"TemporaryIPCBlobParent.cpp",
]
IPDL_SOURCES += [
"BlobTypes.ipdlh",
"IPCBlob.ipdlh",
"PFileCreator.ipdl",
"PRemoteLazyInputStream.ipdl",

Просмотреть файл

@ -13,17 +13,5 @@ interface nsIInputStream;
[scriptable, builtinclass, uuid(4125585f-b0c2-4964-a83c-4b0d99f26d49)]
interface mozIRemoteLazyInputStream : nsISupports
{
/**
* 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;
[notxpcom, noscript] nsIInputStream GetInternalStream();
};

Просмотреть файл

@ -140,8 +140,7 @@ NS_IMETHODIMP BlobURLInputStream::AsyncWait(nsIInputStreamCallback* aCallback,
}
// Pre-empting a valid callback with another is not allowed.
if (NS_WARN_IF(mAsyncWaitCallback && aCallback &&
mAsyncWaitCallback != aCallback)) {
if (NS_WARN_IF(mAsyncWaitCallback && aCallback)) {
return NS_ERROR_FAILURE;
}

Просмотреть файл

@ -4,6 +4,10 @@
include protocol PBackgroundFileRequest;
include protocol PBackgroundMutableFile;
include protocol PChildToParentStream; // FIXME: bug 792908
include protocol PFileDescriptorSet; // FIXME: bug 792908
include protocol PParentToChildStream; // FIXME: bug 792908
include protocol PRemoteLazyInputStream; // FIXME: bug 792908
include IPCBlob;

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

@ -5,6 +5,10 @@
include protocol PBackgroundIDBTransaction;
include protocol PBackgroundIDBVersionChangeTransaction;
include protocol PBackgroundMutableFile;
include protocol PChildToParentStream; // FIXME: bug 792908
include protocol PFileDescriptorSet; // FIXME: bug 792908
include protocol PParentToChildStream; // FIXME: bug 792908
include protocol PRemoteLazyInputStream; // FIXME: bug 792908
include PBackgroundIDBSharedTypes;

Просмотреть файл

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

Просмотреть файл

@ -5,6 +5,10 @@
include protocol PBackgroundIDBTransaction;
include protocol PBackgroundIDBVersionChangeTransaction;
include protocol PBackgroundMutableFile;
include protocol PChildToParentStream; // FIXME: bug 792908
include protocol PFileDescriptorSet; // FIXME: bug 792908
include protocol PParentToChildStream; // FIXME: bug 792908
include protocol PRemoteLazyInputStream; // FIXME: bug 792908
include PBackgroundIDBSharedTypes;

Просмотреть файл

@ -4,6 +4,10 @@
include protocol PBackgroundIDBDatabaseFile;
include protocol PBackgroundMutableFile;
include protocol PChildToParentStream; // FIXME: bug 792908
include protocol PFileDescriptorSet; // FIXME: bug 792908
include protocol PParentToChildStream; // FIXME: bug 792908
include protocol PRemoteLazyInputStream; // FIXME: bug 792908
include DOMTypes;
include IPCBlob;

Просмотреть файл

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

Просмотреть файл

@ -98,8 +98,11 @@
#include "mozilla/intl/LocaleService.h"
#include "mozilla/ipc/BackgroundChild.h"
#include "mozilla/ipc/Endpoint.h"
#include "mozilla/ipc/FileDescriptorSetChild.h"
#include "mozilla/ipc/FileDescriptorUtils.h"
#include "mozilla/ipc/GeckoChildProcessHost.h"
#include "mozilla/ipc/PChildToParentStreamChild.h"
#include "mozilla/ipc/PParentToChildStreamChild.h"
#include "mozilla/ipc/ProcessChild.h"
#include "mozilla/ipc/TestShellChild.h"
#include "mozilla/layers/APZChild.h"
@ -247,6 +250,9 @@
#include "mozilla/dom/File.h"
#include "mozilla/dom/MediaControllerBinding.h"
#include "mozilla/ipc/IPCStreamAlloc.h"
#include "mozilla/ipc/IPCStreamDestination.h"
#include "mozilla/ipc/IPCStreamSource.h"
#ifdef MOZ_WEBSPEECH
# include "mozilla/dom/PSpeechSynthesisChild.h"
@ -1878,6 +1884,36 @@ void ContentChild::GetAvailableDictionaries(
aDictionaries = mAvailableDictionaries.Clone();
}
PFileDescriptorSetChild* ContentChild::SendPFileDescriptorSetConstructor(
const FileDescriptor& aFD) {
MOZ_ASSERT(NS_IsMainThread());
if (IsShuttingDown()) {
return nullptr;
}
return PContentChild::SendPFileDescriptorSetConstructor(aFD);
}
PFileDescriptorSetChild* ContentChild::AllocPFileDescriptorSetChild(
const FileDescriptor& aFD) {
return new FileDescriptorSetChild(aFD);
}
bool ContentChild::DeallocPFileDescriptorSetChild(
PFileDescriptorSetChild* aActor) {
delete static_cast<FileDescriptorSetChild*>(aActor);
return true;
}
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(
@ -1992,6 +2028,37 @@ PRemotePrintJobChild* ContentChild::AllocPRemotePrintJobChild() {
#endif
}
PChildToParentStreamChild* ContentChild::SendPChildToParentStreamConstructor(
PChildToParentStreamChild* aActor) {
MOZ_ASSERT(NS_IsMainThread());
if (IsShuttingDown()) {
return nullptr;
}
return PContentChild::SendPChildToParentStreamConstructor(aActor);
}
PChildToParentStreamChild* ContentChild::AllocPChildToParentStreamChild() {
MOZ_CRASH("PChildToParentStreamChild actors should be manually constructed!");
}
bool ContentChild::DeallocPChildToParentStreamChild(
PChildToParentStreamChild* aActor) {
delete aActor;
return true;
}
PParentToChildStreamChild* ContentChild::AllocPParentToChildStreamChild() {
return mozilla::ipc::AllocPParentToChildStreamChild();
}
bool ContentChild::DeallocPParentToChildStreamChild(
PParentToChildStreamChild* aActor) {
delete aActor;
return true;
}
media::PMediaChild* ContentChild::AllocPMediaChild() {
return media::AllocPMediaChild();
}

Просмотреть файл

@ -45,6 +45,11 @@ class RemoteSpellcheckEngineChild;
class ChildProfilerController;
class BenchmarkStorageChild;
namespace ipc {
class PChildToParentStreamChild;
class PFileDescriptorSetChild;
} // namespace ipc
namespace loader {
class PScriptCacheChild;
}
@ -68,9 +73,11 @@ enum class CallerType : uint32_t;
class ContentChild final : public PContentChild,
public nsIDOMProcessChild,
public mozilla::ipc::IShmemAllocator,
public mozilla::ipc::ChildToParentStreamActorManager,
public ProcessActor {
using ClonedMessageData = mozilla::dom::ClonedMessageData;
using FileDescriptor = mozilla::ipc::FileDescriptor;
using PFileDescriptorSetChild = mozilla::ipc::PFileDescriptorSetChild;
friend class PContentChild;
@ -176,6 +183,9 @@ 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*);
@ -222,6 +232,12 @@ class ContentChild final : public PContentChild,
PRemotePrintJobChild* AllocPRemotePrintJobChild();
PChildToParentStreamChild* AllocPChildToParentStreamChild();
bool DeallocPChildToParentStreamChild(PChildToParentStreamChild*);
PParentToChildStreamChild* AllocPParentToChildStreamChild();
bool DeallocPParentToChildStreamChild(PParentToChildStreamChild*);
PMediaChild* AllocPMediaChild();
bool DeallocPMediaChild(PMediaChild* aActor);
@ -457,6 +473,10 @@ class ContentChild final : public PContentChild,
bool IsForBrowser() const { return mIsForBrowser; }
PFileDescriptorSetChild* AllocPFileDescriptorSetChild(const FileDescriptor&);
bool DeallocPFileDescriptorSetChild(PFileDescriptorSetChild*);
MOZ_CAN_RUN_SCRIPT_BOUNDARY mozilla::ipc::IPCResult RecvConstructBrowser(
ManagedEndpoint<PBrowserChild>&& aBrowserEp,
ManagedEndpoint<PWindowGlobalChild>&& aWindowEp, const TabId& aTabId,
@ -634,6 +654,11 @@ class ContentChild final : public PContentChild,
Endpoint<PSandboxTestingChild>&& aEndpoint);
#endif
PChildToParentStreamChild* SendPChildToParentStreamConstructor(
PChildToParentStreamChild* aActor) override;
PFileDescriptorSetChild* SendPFileDescriptorSetConstructor(
const FileDescriptor& aFD) override;
private:
static void ForceKillTimerCallback(nsITimer* aTimer, void* aClosure);
void StartForceKillTimer();

Просмотреть файл

@ -147,8 +147,13 @@
#include "mozilla/ipc/ByteBuf.h"
#include "mozilla/ipc/CrashReporterHost.h"
#include "mozilla/ipc/Endpoint.h"
#include "mozilla/ipc/FileDescriptorSetParent.h"
#include "mozilla/ipc/FileDescriptorUtils.h"
#include "mozilla/ipc/IPCStreamAlloc.h"
#include "mozilla/ipc/IPCStreamDestination.h"
#include "mozilla/ipc/IPCStreamSource.h"
#include "mozilla/ipc/IPCStreamUtils.h"
#include "mozilla/ipc/PChildToParentStreamParent.h"
#include "mozilla/ipc/TestShellParent.h"
#include "mozilla/layers/CompositorThread.h"
#include "mozilla/layers/ImageBridgeParent.h"
@ -4332,6 +4337,27 @@ mozilla::ipc::IPCResult ContentParent::RecvInitStreamFilter(
return IPC_OK();
}
PChildToParentStreamParent* ContentParent::AllocPChildToParentStreamParent() {
return mozilla::ipc::AllocPChildToParentStreamParent();
}
bool ContentParent::DeallocPChildToParentStreamParent(
PChildToParentStreamParent* aActor) {
delete aActor;
return true;
}
PParentToChildStreamParent* ContentParent::AllocPParentToChildStreamParent() {
MOZ_CRASH(
"PParentToChildStreamParent actors should be manually constructed!");
}
bool ContentParent::DeallocPParentToChildStreamParent(
PParentToChildStreamParent* aActor) {
delete aActor;
return true;
}
mozilla::ipc::IPCResult ContentParent::RecvAddSecurityState(
const MaybeDiscarded<WindowContext>& aContext, uint32_t aStateFlags) {
if (aContext.IsNullOrDiscarded()) {
@ -5011,6 +5037,17 @@ ContentParent::AllocPExtensionsParent() {
return MakeAndAddRef<extensions::ExtensionsParent>();
}
PFileDescriptorSetParent* ContentParent::AllocPFileDescriptorSetParent(
const FileDescriptor& aFD) {
return new FileDescriptorSetParent(aFD);
}
bool ContentParent::DeallocPFileDescriptorSetParent(
PFileDescriptorSetParent* aActor) {
delete static_cast<FileDescriptorSetParent*>(aActor);
return true;
}
void ContentParent::NotifyUpdatedDictionaries() {
RefPtr<mozSpellChecker> spellChecker(mozSpellChecker::Create());
MOZ_ASSERT(spellChecker, "No spell checker?");
@ -7232,6 +7269,18 @@ mozilla::ipc::IPCResult ContentParent::RecvCommitBrowsingContextTransaction(
return aTransaction.CommitFromIPC(aContext, this);
}
PParentToChildStreamParent* ContentParent::SendPParentToChildStreamConstructor(
PParentToChildStreamParent* aActor) {
MOZ_ASSERT(NS_IsMainThread());
return PContentParent::SendPParentToChildStreamConstructor(aActor);
}
PFileDescriptorSetParent* ContentParent::SendPFileDescriptorSetConstructor(
const FileDescriptor& aFD) {
MOZ_ASSERT(NS_IsMainThread());
return PContentParent::SendPFileDescriptorSetConstructor(aFD);
}
mozilla::ipc::IPCResult ContentParent::RecvBlobURLDataRequest(
const nsCString& aBlobURL, nsIPrincipal* aTriggeringPrincipal,
nsIPrincipal* aLoadingPrincipal, const OriginAttributes& aOriginAttributes,

Просмотреть файл

@ -20,6 +20,8 @@
#include "mozilla/ipc/BackgroundUtils.h"
#include "mozilla/ipc/GeckoChildProcessHost.h"
#include "mozilla/ipc/InputStreamUtils.h"
#include "mozilla/ipc/PParentToChildStreamParent.h"
#include "mozilla/ipc/PChildToParentStreamParent.h"
#include "mozilla/Attributes.h"
#include "mozilla/DataMutex.h"
#include "mozilla/FileUtils.h"
@ -74,6 +76,7 @@ using mozilla::loader::PScriptCacheParent;
namespace ipc {
class CrashReporterHost;
class PFileDescriptorSetParent;
class TestShellParent;
#ifdef FUZZING
class ProtocolFuzzerHelper;
@ -105,21 +108,24 @@ struct CancelContentJSOptions;
} \
}
class ContentParent final : public PContentParent,
public nsIDOMProcessParent,
public nsIObserver,
public nsIDOMGeoPositionCallback,
public nsIDOMGeoPositionErrorCallback,
public nsIAsyncShutdownBlocker,
public nsIInterfaceRequestor,
public gfx::gfxVarReceiver,
public mozilla::LinkedListElement<ContentParent>,
public gfx::GPUProcessListener,
public mozilla::MemoryReportingProcess,
public mozilla::dom::ipc::MessageManagerCallback,
public mozilla::ipc::IShmemAllocator,
public ProcessActor {
class ContentParent final
: public PContentParent,
public nsIDOMProcessParent,
public nsIObserver,
public nsIDOMGeoPositionCallback,
public nsIDOMGeoPositionErrorCallback,
public nsIAsyncShutdownBlocker,
public nsIInterfaceRequestor,
public gfx::gfxVarReceiver,
public mozilla::LinkedListElement<ContentParent>,
public gfx::GPUProcessListener,
public mozilla::MemoryReportingProcess,
public mozilla::dom::ipc::MessageManagerCallback,
public mozilla::ipc::IShmemAllocator,
public mozilla::ipc::ParentToChildStreamActorManager,
public ProcessActor {
typedef mozilla::ipc::GeckoChildProcessHost GeckoChildProcessHost;
typedef mozilla::ipc::PFileDescriptorSetParent PFileDescriptorSetParent;
typedef mozilla::ipc::TestShellParent TestShellParent;
typedef mozilla::ipc::PrincipalInfo PrincipalInfo;
typedef mozilla::dom::ClonedMessageData ClonedMessageData;
@ -444,6 +450,12 @@ class ContentParent final : public PContentParent,
const uint64_t& aChannelId, const nsString& aAddonId,
InitStreamFilterResolver&& aResolver);
PChildToParentStreamParent* AllocPChildToParentStreamParent();
bool DeallocPChildToParentStreamParent(PChildToParentStreamParent* aActor);
PParentToChildStreamParent* AllocPParentToChildStreamParent();
bool DeallocPParentToChildStreamParent(PParentToChildStreamParent* aActor);
PHalParent* AllocPHalParent();
virtual mozilla::ipc::IPCResult RecvPHalConstructor(
@ -671,6 +683,11 @@ class ContentParent final : public PContentParent,
FORWARD_SHMEM_ALLOCATOR_TO(PContentParent)
PParentToChildStreamParent* SendPParentToChildStreamConstructor(
PParentToChildStreamParent* aActor) override;
PFileDescriptorSetParent* SendPFileDescriptorSetConstructor(
const FileDescriptor& aFD) override;
mozilla::ipc::IPCResult RecvBlobURLDataRequest(
const nsCString& aBlobURL, nsIPrincipal* pTriggeringPrincipal,
nsIPrincipal* pLoadingPrincipal,
@ -1139,6 +1156,11 @@ class ContentParent final : public PContentParent,
already_AddRefed<extensions::PExtensionsParent> AllocPExtensionsParent();
PFileDescriptorSetParent* AllocPFileDescriptorSetParent(
const mozilla::ipc::FileDescriptor&);
bool DeallocPFileDescriptorSetParent(PFileDescriptorSetParent*);
#ifdef MOZ_WEBRTC
PWebrtcGlobalParent* AllocPWebrtcGlobalParent();
bool DeallocPWebrtcGlobalParent(PWebrtcGlobalParent* aActor);

Просмотреть файл

@ -17,6 +17,7 @@ include "mozilla/net/ClassOfService.h";
include IPCBlob;
include IPCStream;
include protocol PRemoteLazyInputStream;
include ProtocolTypes;
using struct mozilla::void_t from "mozilla/ipc/IPCCore.h";
@ -51,7 +52,6 @@ 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,8 +345,7 @@ struct ReplacementChannelConfigInit
nsCString? method;
nsIReferrerInfo referrerInfo;
TimedChannelInfo? timedChannelInfo;
RemoteLazyInputStream uploadStream;
uint64_t uploadStreamLength;
nullable PRemoteLazyInputStream uploadStream;
bool uploadStreamHasHeaders;
nsCString? contentType;
nsCString? contentLength;

Просмотреть файл

@ -12,6 +12,10 @@ include protocol PDocAccessible;
#endif
include protocol PFilePicker;
include protocol PRemotePrintJob;
include protocol PChildToParentStream;
include protocol PParentToChildStream;
include protocol PFileDescriptorSet;
include protocol PRemoteLazyInputStream;
include protocol PPaymentRequest;
include protocol PSessionStore;
include protocol PWindowGlobal;

Просмотреть файл

@ -13,10 +13,12 @@ include protocol PDocumentChannel;
include protocol PExtensions;
include protocol PExternalHelperApp;
include protocol PHandlerService;
include protocol PFileDescriptorSet;
include protocol PHal;
include protocol PHeapSnapshotTempFileHelper;
include protocol PProcessHangMonitor;
include protocol PImageBridge;
include protocol PRemoteLazyInputStream;
include protocol PRemotePrintJob;
include protocol PLoginReputation;
include protocol PMedia;
@ -25,6 +27,8 @@ include protocol PStreamFilter;
include protocol PGMPContent;
include protocol PGMPService;
include protocol PGMP;
include protocol PChildToParentStream;
include protocol PParentToChildStream;
#ifdef MOZ_WEBSPEECH
include protocol PSpeechSynthesis;
#endif
@ -459,12 +463,16 @@ sync protocol PContent
manages PCycleCollectWithLogs;
manages PExtensions;
manages PExternalHelperApp;
manages PFileDescriptorSet;
manages PHal;
manages PHandlerService;
manages PHeapSnapshotTempFileHelper;
manages PRemoteLazyInputStream;
manages PRemotePrintJob;
manages PMedia;
manages PNecko;
manages PChildToParentStream;
manages PParentToChildStream;
#ifdef MOZ_WEBSPEECH
manages PSpeechSynthesis;
#endif
@ -535,6 +543,8 @@ child:
bool isForBrowser, bool isTopLevel);
both:
async PFileDescriptorSet(FileDescriptor fd);
// For parent->child, aBrowser must be non-null; aContext can
// be null to indicate the browser's current root document, or non-null
// to persist a subdocument. For child->parent, arguments are
@ -853,12 +863,16 @@ child:
async GMPsChanged(GMPCapabilityData[] capabilities);
async PParentToChildStream();
async ProvideAnonymousTemporaryFile(uint64_t aID, FileDescOrError aFD);
async SetPermissionsWithKey(nsCString aPermissionKey, Permission[] aPermissions);
async RefreshScreens(ScreenDetails[] aScreens);
async PRemoteLazyInputStream(nsID aID, uint64_t aSize);
async ShareCodeCoverageMutex(CrossProcessMutexHandle handle);
async FlushCodeCoverageCounters() returns (bool unused);
@ -1076,6 +1090,8 @@ parent:
async PNecko();
async PChildToParentStream();
#ifdef MOZ_WEBSPEECH
async PSpeechSynthesis();
#endif

Просмотреть файл

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

Просмотреть файл

@ -25,6 +25,7 @@ using namespace mozilla::ipc;
namespace mozilla::dom::ipc {
using mozilla::ipc::AutoIPCStream;
using mozilla::ipc::IPCStream;
using mozilla::ipc::PBackgroundChild;
using mozilla::ipc::PBackgroundParent;
@ -61,6 +62,7 @@ StructuredCloneData& StructuredCloneData::operator=(
mBlobImplArray = std::move(aOther.mBlobImplArray);
mExternalData = std::move(aOther.mExternalData);
mSharedData = std::move(aOther.mSharedData);
mIPCStreams = std::move(aOther.mIPCStreams);
mInitialized = aOther.mInitialized;
return *this;
@ -179,16 +181,24 @@ bool BuildClonedMessageData(M* aManager, StructuredCloneData& aData,
const nsTArray<nsCOMPtr<nsIInputStream>>& inputStreams = aData.InputStreams();
if (!inputStreams.IsEmpty()) {
if (NS_WARN_IF(
!aData.IPCStreams().SetCapacity(inputStreams.Length(), fallible))) {
return false;
}
nsTArray<IPCStream>& streams = aClonedData.inputStreams();
uint32_t length = inputStreams.Length();
streams.SetCapacity(length);
for (uint32_t i = 0; i < length; ++i) {
IPCStream value;
if (!mozilla::ipc::SerializeIPCStream(do_AddRef(inputStreams[i]), value,
/* aAllowLazy */ false)) {
AutoIPCStream* stream = aData.IPCStreams().AppendElement(fallible);
if (NS_WARN_IF(!stream)) {
return false;
}
streams.AppendElement(value);
if (!stream->Serialize(inputStreams[i], aManager)) {
return false;
}
streams.AppendElement(stream->TakeValue());
}
}

Просмотреть файл

@ -23,6 +23,7 @@ class PickleIterator;
namespace mozilla {
namespace ipc {
class AutoIPCStream;
class PBackgroundChild;
class PBackgroundParent;
@ -274,6 +275,10 @@ class StructuredCloneData : public StructuredCloneHolder {
bool SupportsTransferring() { return mSupportsTransferring; }
FallibleTArray<mozilla::ipc::AutoIPCStream>& IPCStreams() {
return mIPCStreams;
}
// For IPC serialization
void WriteIPCParams(IPC::MessageWriter* aWriter) const;
bool ReadIPCParams(IPC::MessageReader* aReader);
@ -285,6 +290,9 @@ class StructuredCloneData : public StructuredCloneHolder {
JSStructuredCloneData mExternalData;
RefPtr<SharedJSAllocatedData> mSharedData;
// This array is needed because AutoIPCStream DTOR must be executed after the
// sending of the data via IPC. This will be fixed by bug 1353475.
FallibleTArray<mozilla::ipc::AutoIPCStream> mIPCStreams;
bool mInitialized;
};

Просмотреть файл

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

Просмотреть файл

@ -7,6 +7,9 @@
include protocol PNecko;
include protocol PBackground;
include protocol PFileDescriptorSet; // FIXME: bug #792908
include protocol PChildToParentStream; //FIXME: bug #792908
include protocol PParentToChildStream; //FIXME: bug #792908
include IPCStream;

Просмотреть файл

@ -142,15 +142,13 @@ nsresult UDPSocketChild::SendBinaryStream(const nsACString& aHost,
nsIInputStream* aStream) {
NS_ENSURE_ARG(aStream);
mozilla::ipc::IPCStream stream;
if (NS_WARN_IF(!mozilla::ipc::SerializeIPCStream(do_AddRef(aStream), stream,
/* aAllowLazy */ false))) {
return NS_ERROR_UNEXPECTED;
}
mozilla::ipc::AutoIPCStream autoStream;
autoStream.Serialize(aStream, static_cast<mozilla::dom::ContentChild*>(
gNeckoChild->Manager()));
UDPSOCKET_LOG(
("%s: %s:%u", __FUNCTION__, PromiseFlatCString(aHost).get(), aPort));
SendOutgoingData(UDPData(stream),
SendOutgoingData(UDPData(autoStream.TakeValue()),
UDPSocketAddr(UDPAddressInfo(nsCString(aHost), aPort)));
return NS_OK;

Просмотреть файл

@ -78,12 +78,12 @@ NS_IMETHODIMP DecryptingInputStreamBase::GetCloneable(bool* aCloneable) {
return NS_OK;
}
void DecryptingInputStreamBase::SerializedComplexity(uint32_t aMaxSize,
uint32_t* aSizeUsed,
uint32_t* aPipes,
uint32_t* aTransferables) {
(*mBaseIPCSerializableInputStream)
->SerializedComplexity(aMaxSize, aSizeUsed, aPipes, aTransferables);
void DecryptingInputStreamBase::Serialize(
mozilla::ipc::InputStreamParams& aParams,
FileDescriptorArray& aFileDescriptors, bool aDelayedStart,
uint32_t aMaxSize, uint32_t* aSizeUsed,
mozilla::ipc::ChildToParentStreamActorManager* aManager) {
MOZ_CRASH("Not implemented");
}
size_t DecryptingInputStreamBase::PlainLength() const {

Просмотреть файл

@ -28,6 +28,11 @@
#include "nsTArray.h"
#include "nscore.h"
namespace mozilla::ipc {
class ChildToParentStreamActorManager;
class ParentToChildStreamActorManager;
} // namespace mozilla::ipc
template <class T>
class nsCOMPtr;
@ -48,9 +53,11 @@ class DecryptingInputStreamBase : public nsIInputStream,
using nsICloneableInputStream::GetCloneable;
NS_IMETHOD GetCloneable(bool* aCloneable) final;
void SerializedComplexity(uint32_t aMaxSize, uint32_t* aSizeUsed,
uint32_t* aPipes,
uint32_t* aTransferables) override;
using nsIIPCSerializableInputStream::Serialize;
void Serialize(mozilla::ipc::InputStreamParams& aParams,
FileDescriptorArray& aFileDescriptors, bool aDelayedStart,
uint32_t aMaxSize, uint32_t* aSizeUsed,
mozilla::ipc::ChildToParentStreamActorManager* aManager) final;
protected:
DecryptingInputStreamBase(MovingNotNull<nsCOMPtr<nsIInputStream>> aBaseStream,
@ -116,10 +123,15 @@ class DecryptingInputStream final : public DecryptingInputStreamBase {
NS_IMETHOD Clone(nsIInputStream** _retval) override;
void Serialize(mozilla::ipc::InputStreamParams& aParams, uint32_t aMaxSize,
uint32_t* aSizeUsed) override;
using DecryptingInputStreamBase::Serialize;
void Serialize(
mozilla::ipc::InputStreamParams& aParams,
FileDescriptorArray& aFileDescriptors, bool aDelayedStart,
uint32_t aMaxSize, uint32_t* aSizeUsed,
mozilla::ipc::ParentToChildStreamActorManager* aManager) override;
bool Deserialize(const mozilla::ipc::InputStreamParams& aParams) override;
bool Deserialize(const mozilla::ipc::InputStreamParams& aParams,
const FileDescriptorArray& aFileDescriptors) override;
private:
~DecryptingInputStream();

Просмотреть файл

@ -464,14 +464,17 @@ NS_IMETHODIMP DecryptingInputStream<CipherStrategy>::Clone(
template <typename CipherStrategy>
void DecryptingInputStream<CipherStrategy>::Serialize(
mozilla::ipc::InputStreamParams& aParams, uint32_t aMaxSize,
uint32_t* aSizeUsed) {
mozilla::ipc::InputStreamParams& aParams,
FileDescriptorArray& aFileDescriptors, bool aDelayedStart,
uint32_t aMaxSize, uint32_t* aSizeUsed,
mozilla::ipc::ParentToChildStreamActorManager* aManager) {
MOZ_ASSERT(mBaseStream);
MOZ_ASSERT(mBaseIPCSerializableInputStream);
mozilla::ipc::InputStreamParams baseStreamParams;
(*mBaseIPCSerializableInputStream)
->Serialize(baseStreamParams, aMaxSize, aSizeUsed);
->Serialize(baseStreamParams, aFileDescriptors, aDelayedStart, aMaxSize,
aSizeUsed, aManager);
MOZ_ASSERT(baseStreamParams.type() ==
mozilla::ipc::InputStreamParams::TFileInputStreamParams);
@ -488,7 +491,8 @@ void DecryptingInputStream<CipherStrategy>::Serialize(
template <typename CipherStrategy>
bool DecryptingInputStream<CipherStrategy>::Deserialize(
const mozilla::ipc::InputStreamParams& aParams) {
const mozilla::ipc::InputStreamParams& aParams,
const FileDescriptorArray& aFileDescriptors) {
MOZ_ASSERT(aParams.type() ==
mozilla::ipc::InputStreamParams::TEncryptedFileInputStreamParams);
const auto& params = aParams.get_EncryptedFileInputStreamParams();
@ -499,8 +503,8 @@ bool DecryptingInputStream<CipherStrategy>::Deserialize(
nsCOMPtr<nsIIPCSerializableInputStream> baseSerializable =
do_QueryInterface(stream);
if (NS_WARN_IF(
!baseSerializable->Deserialize(params.fileInputStreamParams()))) {
if (NS_WARN_IF(!baseSerializable->Deserialize(params.fileInputStreamParams(),
aFileDescriptors))) {
return false;
}

Просмотреть файл

@ -37,7 +37,8 @@ namespace {
nsresult GetIPCSynthesizeResponseArgs(
ChildToParentSynthesizeResponseArgs* aIPCArgs,
SynthesizeResponseArgs&& aArgs) {
SynthesizeResponseArgs&& aArgs, UniquePtr<AutoIPCStream>& aAutoBodyStream,
UniquePtr<AutoIPCStream>& aAutoAlternativeBodyStream) {
MOZ_ASSERT(RemoteWorkerService::Thread()->IsOnCurrentThread());
SafeRefPtr<InternalResponse> internalResponse;
@ -55,7 +56,8 @@ nsresult GetIPCSynthesizeResponseArgs(
}
internalResponse->ToChildToParentInternalResponse(
&aIPCArgs->internalResponse(), bgChild);
&aIPCArgs->internalResponse(), bgChild, aAutoBodyStream,
aAutoAlternativeBodyStream);
return NS_OK;
}
@ -133,8 +135,13 @@ void FetchEventOpProxyChild::Initialize(
if (result.is<SynthesizeResponseArgs>()) {
ChildToParentSynthesizeResponseArgs ipcArgs;
UniquePtr<AutoIPCStream> autoBodyStream =
MakeUnique<AutoIPCStream>();
UniquePtr<AutoIPCStream> autoAlternativeBodyStream =
MakeUnique<AutoIPCStream>();
nsresult rv = GetIPCSynthesizeResponseArgs(
&ipcArgs, result.extract<SynthesizeResponseArgs>());
&ipcArgs, result.extract<SynthesizeResponseArgs>(),
autoBodyStream, autoAlternativeBodyStream);
if (NS_WARN_IF(NS_FAILED(rv))) {
Unused << self->SendRespondWith(
@ -143,6 +150,14 @@ void FetchEventOpProxyChild::Initialize(
}
Unused << self->SendRespondWith(ipcArgs);
if (ipcArgs.internalResponse().body()) {
autoBodyStream->TakeValue();
}
if (ipcArgs.internalResponse().alternativeBody()) {
autoAlternativeBodyStream->TakeValue();
}
} else if (result.is<ResetInterceptionArgs>()) {
Unused << self->SendRespondWith(
result.extract<ResetInterceptionArgs>());

Просмотреть файл

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

Просмотреть файл

@ -2063,7 +2063,6 @@ void ServiceWorkerManager::DispatchFetchEvent(nsIInterceptedChannel* aChannel,
ErrorResult& aRv) {
MOZ_ASSERT(aChannel);
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(XRE_IsParentProcess());
nsCOMPtr<nsIChannel> internalChannel;
aRv = aChannel->GetChannel(getter_AddRefs(internalChannel));
@ -2232,13 +2231,28 @@ void ServiceWorkerManager::DispatchFetchEvent(nsIInterceptedChannel* aChannel,
// When this service worker was registered, we also sent down the permissions
// for the runnable. They should have arrived by now, but we still need to
// wait for them if they have not.
RefPtr<PermissionManager> permMgr = PermissionManager::GetInstance();
if (permMgr) {
permMgr->WhenPermissionsAvailable(serviceWorker->Principal(),
continueRunnable);
} else {
continueRunnable->HandleError();
nsCOMPtr<nsIRunnable> permissionsRunnable = NS_NewRunnableFunction(
"dom::ServiceWorkerManager::DispatchFetchEvent", [=]() {
RefPtr<PermissionManager> permMgr = PermissionManager::GetInstance();
if (permMgr) {
permMgr->WhenPermissionsAvailable(serviceWorker->Principal(),
continueRunnable);
} else {
continueRunnable->HandleError();
}
});
nsCOMPtr<nsIUploadChannel2> uploadChannel =
do_QueryInterface(internalChannel);
// If there is no upload stream, then continue immediately
if (!uploadChannel) {
MOZ_ALWAYS_SUCCEEDS(permissionsRunnable->Run());
return;
}
// Otherwise, ensure the upload stream can be cloned directly. This may
// require some async copying, so provide a callback.
aRv = uploadChannel->EnsureUploadStreamIsCloneable(permissionsRunnable);
}
bool ServiceWorkerManager::IsAvailable(nsIPrincipal* aPrincipal, nsIURI* aURI,

Просмотреть файл

@ -863,6 +863,7 @@ 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) {
@ -883,7 +884,8 @@ nsresult MaybeStoreStreamForBackgroundThread(nsIInterceptedChannel* aChannel,
}
auto storage = storageOrErr.unwrap();
storage->AddStream(uploadStream, body->get_ParentToParentStream().uuid());
storage->AddStream(uploadStream, body->get_ParentToParentStream().uuid(),
bodySize, 0);
}
}

Просмотреть файл

@ -6,6 +6,9 @@
include protocol PContent;
include protocol PWebBrowserPersistResources;
include protocol PWebBrowserPersistSerialize;
include protocol PFileDescriptorSet;
include protocol PChildToParentStream; //FIXME: bug #792908
include protocol PParentToChildStream; //FIXME: bug #792908
include PBackgroundSharedTypes;
include IPCStream;

Просмотреть файл

@ -76,12 +76,12 @@ void WebBrowserPersistDocumentChild::Start(
ENSURE(aDocument->GetPostData(getter_AddRefs(postDataStream)));
#undef ENSURE
Maybe<mozilla::ipc::IPCStream> stream;
mozilla::ipc::SerializeIPCStream(postDataStream.forget(), stream,
/* aAllowLazy */ false);
mozilla::ipc::AutoIPCStream autoStream;
autoStream.Serialize(postDataStream,
static_cast<mozilla::dom::ContentChild*>(Manager()));
mDocument = aDocument;
SendAttributes(attrs, stream);
SendAttributes(attrs, autoStream.TakeOptionalValue());
}
mozilla::ipc::IPCResult WebBrowserPersistDocumentChild::RecvSetPersistFlags(

Просмотреть файл

@ -13,6 +13,7 @@
#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"

Просмотреть файл

@ -8,6 +8,7 @@
#include "ActorsChild.h" // IndexedDB
#include "BroadcastChannelChild.h"
#include "FileDescriptorSetChild.h"
#ifdef MOZ_WEBRTC
# include "CamerasChild.h"
#endif
@ -45,7 +46,10 @@
#include "mozilla/dom/ServiceWorkerContainerChild.h"
#include "mozilla/dom/ServiceWorkerManagerChild.h"
#include "mozilla/dom/BrowserChild.h"
#include "mozilla/ipc/IPCStreamAlloc.h"
#include "mozilla/ipc/PBackgroundTestChild.h"
#include "mozilla/ipc/PChildToParentStreamChild.h"
#include "mozilla/ipc/PParentToChildStreamChild.h"
#include "mozilla/net/HttpBackgroundChannelChild.h"
#include "mozilla/net/PUDPSocketChild.h"
#include "mozilla/dom/network/UDPSocketChild.h"
@ -383,6 +387,27 @@ 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();
}
PFileDescriptorSetChild* BackgroundChildImpl::AllocPFileDescriptorSetChild(
const FileDescriptor& aFileDescriptor) {
return new FileDescriptorSetChild(aFileDescriptor);
}
bool BackgroundChildImpl::DeallocPFileDescriptorSetChild(
PFileDescriptorSetChild* aActor) {
MOZ_ASSERT(aActor);
delete static_cast<FileDescriptorSetChild*>(aActor);
return true;
}
PUDPSocketChild* BackgroundChildImpl::AllocPUDPSocketChild(
const Maybe<PrincipalInfo>& aPrincipalInfo, const nsCString& aFilter) {
MOZ_CRASH("AllocPUDPSocket should not be called");
@ -500,6 +525,28 @@ bool BackgroundChildImpl::DeallocPMessagePortChild(PMessagePortChild* aActor) {
return true;
}
PChildToParentStreamChild*
BackgroundChildImpl::AllocPChildToParentStreamChild() {
MOZ_CRASH("PChildToParentStreamChild actors should be manually constructed!");
}
bool BackgroundChildImpl::DeallocPChildToParentStreamChild(
PChildToParentStreamChild* aActor) {
delete aActor;
return true;
}
PParentToChildStreamChild*
BackgroundChildImpl::AllocPParentToChildStreamChild() {
return mozilla::ipc::AllocPParentToChildStreamChild();
}
bool BackgroundChildImpl::DeallocPParentToChildStreamChild(
PParentToChildStreamChild* aActor) {
delete aActor;
return true;
}
BackgroundChildImpl::PQuotaChild* BackgroundChildImpl::AllocPQuotaChild() {
MOZ_CRASH("PQuotaChild actor should be manually constructed!");
}
@ -624,6 +671,17 @@ bool BackgroundChildImpl::DeallocPMediaTransportChild(
return true;
}
PChildToParentStreamChild*
BackgroundChildImpl::SendPChildToParentStreamConstructor(
PChildToParentStreamChild* aActor) {
return PBackgroundChild::SendPChildToParentStreamConstructor(aActor);
}
PFileDescriptorSetChild* BackgroundChildImpl::SendPFileDescriptorSetConstructor(
const FileDescriptor& aFD) {
return PBackgroundChild::SendPFileDescriptorSetConstructor(aFD);
}
} // namespace mozilla::ipc
mozilla::ipc::IPCResult TestChild::Recv__delete__(const nsCString& aTestArg) {

Просмотреть файл

@ -29,7 +29,8 @@ namespace ipc {
// Instances of this class should never be created directly. This class is meant
// to be inherited in BackgroundImpl.
class BackgroundChildImpl : public PBackgroundChild {
class BackgroundChildImpl : public PBackgroundChild,
public ChildToParentStreamActorManager {
public:
class ThreadLocal;
@ -40,6 +41,11 @@ class BackgroundChildImpl : public PBackgroundChild {
// This functions is implemented in BackgroundImpl.cpp.
static ThreadLocal* GetThreadLocalForCurrentThread();
PChildToParentStreamChild* SendPChildToParentStreamConstructor(
PChildToParentStreamChild* aActor) override;
PFileDescriptorSetChild* SendPFileDescriptorSetConstructor(
const FileDescriptor& aFD) override;
protected:
BackgroundChildImpl();
virtual ~BackgroundChildImpl();
@ -107,6 +113,10 @@ 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(
@ -148,6 +158,12 @@ class BackgroundChildImpl : public PBackgroundChild {
virtual bool DeallocPSharedWorkerChild(
mozilla::dom::PSharedWorkerChild* aActor) override;
virtual PFileDescriptorSetChild* AllocPFileDescriptorSetChild(
const FileDescriptor& aFileDescriptor) override;
virtual bool DeallocPFileDescriptorSetChild(
PFileDescriptorSetChild* aActor) override;
virtual PCamerasChild* AllocPCamerasChild() override;
virtual bool DeallocPCamerasChild(PCamerasChild* aActor) override;
@ -190,6 +206,16 @@ class BackgroundChildImpl : public PBackgroundChild {
virtual bool DeallocPMessagePortChild(PMessagePortChild* aActor) override;
virtual PChildToParentStreamChild* AllocPChildToParentStreamChild() override;
virtual bool DeallocPChildToParentStreamChild(
PChildToParentStreamChild* aActor) override;
virtual PParentToChildStreamChild* AllocPParentToChildStreamChild() override;
virtual bool DeallocPParentToChildStreamChild(
PParentToChildStreamChild* aActor) override;
virtual PQuotaChild* AllocPQuotaChild() override;
virtual bool DeallocPQuotaChild(PQuotaChild* aActor) override;

Просмотреть файл

@ -7,6 +7,7 @@
#include "BackgroundParentImpl.h"
#include "BroadcastChannelParent.h"
#include "FileDescriptorSetParent.h"
#ifdef MOZ_WEBRTC
# include "CamerasParent.h"
#endif
@ -61,9 +62,12 @@
#include "mozilla/ipc/BackgroundParent.h"
#include "mozilla/ipc/BackgroundUtils.h"
#include "mozilla/ipc/Endpoint.h"
#include "mozilla/ipc/IPCStreamAlloc.h"
#include "mozilla/ipc/IdleSchedulerParent.h"
#include "mozilla/ipc/PBackgroundSharedTypes.h"
#include "mozilla/ipc/PBackgroundTestParent.h"
#include "mozilla/ipc/PChildToParentStreamParent.h"
#include "mozilla/ipc/PParentToChildStreamParent.h"
#include "mozilla/media/MediaParent.h"
#include "mozilla/net/BackgroundDataBridgeParent.h"
#include "mozilla/net/HttpBackgroundChannelParent.h"
@ -654,6 +658,61 @@ 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();
}
PFileDescriptorSetParent* BackgroundParentImpl::AllocPFileDescriptorSetParent(
const FileDescriptor& aFileDescriptor) {
AssertIsInMainOrSocketProcess();
AssertIsOnBackgroundThread();
return new FileDescriptorSetParent(aFileDescriptor);
}
bool BackgroundParentImpl::DeallocPFileDescriptorSetParent(
PFileDescriptorSetParent* aActor) {
AssertIsInMainOrSocketProcess();
AssertIsOnBackgroundThread();
MOZ_ASSERT(aActor);
delete static_cast<FileDescriptorSetParent*>(aActor);
return true;
}
PChildToParentStreamParent*
BackgroundParentImpl::AllocPChildToParentStreamParent() {
return mozilla::ipc::AllocPChildToParentStreamParent();
}
bool BackgroundParentImpl::DeallocPChildToParentStreamParent(
PChildToParentStreamParent* aActor) {
delete aActor;
return true;
}
PParentToChildStreamParent*
BackgroundParentImpl::AllocPParentToChildStreamParent() {
MOZ_CRASH(
"PParentToChildStreamParent actors should be manually constructed!");
}
bool BackgroundParentImpl::DeallocPParentToChildStreamParent(
PParentToChildStreamParent* aActor) {
delete aActor;
return true;
}
already_AddRefed<BackgroundParentImpl::PVsyncParent>
BackgroundParentImpl::AllocPVsyncParent() {
AssertIsInMainOrSocketProcess();
@ -1439,6 +1498,18 @@ BackgroundParentImpl::AllocPLockManagerParent(
aClientId);
}
PParentToChildStreamParent*
BackgroundParentImpl::SendPParentToChildStreamConstructor(
PParentToChildStreamParent* aActor) {
return PBackgroundParent::SendPParentToChildStreamConstructor(aActor);
}
PFileDescriptorSetParent*
BackgroundParentImpl::SendPFileDescriptorSetConstructor(
const FileDescriptor& aFD) {
return PBackgroundParent::SendPFileDescriptorSetConstructor(aFD);
}
already_AddRefed<mozilla::net::PWebSocketConnectionParent>
BackgroundParentImpl::AllocPWebSocketConnectionParent(
const uint32_t& aListenerId) {

Просмотреть файл

@ -15,7 +15,14 @@ namespace mozilla::ipc {
// Instances of this class should never be created directly. This class is meant
// to be inherited in BackgroundImpl.
class BackgroundParentImpl : public PBackgroundParent {
class BackgroundParentImpl : public PBackgroundParent,
public ParentToChildStreamActorManager {
public:
PParentToChildStreamParent* SendPParentToChildStreamConstructor(
PParentToChildStreamParent* aActor) override;
PFileDescriptorSetParent* SendPFileDescriptorSetConstructor(
const FileDescriptor& aFD) override;
protected:
BackgroundParentImpl();
virtual ~BackgroundParentImpl();
@ -136,6 +143,10 @@ 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(
@ -192,6 +203,12 @@ class BackgroundParentImpl : public PBackgroundParent {
bool DeallocPSharedWorkerParent(PSharedWorkerParent* aActor) override;
PFileDescriptorSetParent* AllocPFileDescriptorSetParent(
const FileDescriptor& aFileDescriptor) override;
bool DeallocPFileDescriptorSetParent(
PFileDescriptorSetParent* aActor) override;
already_AddRefed<PVsyncParent> AllocPVsyncParent() override;
already_AddRefed<mozilla::psm::PVerifySSLServerCertParent>
@ -224,6 +241,16 @@ class BackgroundParentImpl : public PBackgroundParent {
bool DeallocPBroadcastChannelParent(PBroadcastChannelParent* aActor) override;
PChildToParentStreamParent* AllocPChildToParentStreamParent() override;
bool DeallocPChildToParentStreamParent(
PChildToParentStreamParent* aActor) override;
PParentToChildStreamParent* AllocPParentToChildStreamParent() override;
bool DeallocPParentToChildStreamParent(
PParentToChildStreamParent* aActor) override;
PServiceWorkerManagerParent* AllocPServiceWorkerManagerParent() override;
bool DeallocPServiceWorkerManagerParent(

Просмотреть файл

@ -655,23 +655,27 @@ NS_IMETHODIMP DataPipeReceiver::AsyncWait(nsIInputStreamCallback* aCallback,
// nsIIPCSerializableInputStream
void DataPipeReceiver::SerializedComplexity(uint32_t aMaxSize,
uint32_t* aSizeUsed,
uint32_t* aPipes,
uint32_t* aTransferables) {
// We report DataPipeReceiver as taking one transferrable to serialize, rather
// than one pipe, as we aren't starting a new pipe for this purpose, and are
// instead transferring an existing pipe.
*aTransferables = 1;
}
void DataPipeReceiver::Serialize(InputStreamParams& aParams, uint32_t aMaxSize,
uint32_t* aSizeUsed) {
void DataPipeReceiver::Serialize(InputStreamParams& aParams,
FileDescriptorArray& aFileDescriptors,
bool aDelayedStart, uint32_t aMaxSize,
uint32_t* aSizeUsed,
ParentToChildStreamActorManager* aManager) {
*aSizeUsed = 0;
aParams = DataPipeReceiverStreamParams(this);
}
bool DataPipeReceiver::Deserialize(const InputStreamParams& aParams) {
void DataPipeReceiver::Serialize(InputStreamParams& aParams,
FileDescriptorArray& aFileDescriptors,
bool aDelayedStart, uint32_t aMaxSize,
uint32_t* aSizeUsed,
ChildToParentStreamActorManager* aManager) {
*aSizeUsed = 0;
aParams = DataPipeReceiverStreamParams(this);
}
bool DataPipeReceiver::Deserialize(
const InputStreamParams& aParams,
const FileDescriptorArray& aFileDescriptors) {
MOZ_CRASH("Handled directly in `DeserializeInputStream`");
}

Просмотреть файл

@ -0,0 +1,31 @@
/* -*- 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 "FileDescriptorSetChild.h"
namespace mozilla::ipc {
FileDescriptorSetChild::FileDescriptorSetChild(
const FileDescriptor& aFileDescriptor) {
mFileDescriptors.AppendElement(aFileDescriptor);
}
FileDescriptorSetChild::~FileDescriptorSetChild() {
MOZ_ASSERT(mFileDescriptors.IsEmpty());
}
void FileDescriptorSetChild::ForgetFileDescriptors(
nsTArray<FileDescriptor>& aFileDescriptors) {
aFileDescriptors = std::move(mFileDescriptors);
}
mozilla::ipc::IPCResult FileDescriptorSetChild::RecvAddFileDescriptor(
const FileDescriptor& aFileDescriptor) {
mFileDescriptors.AppendElement(aFileDescriptor);
return IPC_OK();
}
} // namespace mozilla::ipc

Просмотреть файл

@ -0,0 +1,56 @@
/* -*- 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_ipc_FileDescriptorSetChild_h__
#define mozilla_ipc_FileDescriptorSetChild_h__
#include "mozilla/Assertions.h"
#include "mozilla/Attributes.h"
#include "mozilla/ipc/PFileDescriptorSetChild.h"
#include "nsTArray.h"
namespace mozilla {
namespace dom {
class ContentChild;
} // namespace dom
namespace net {
class SocketProcessChild;
} // namespace net
namespace ipc {
class BackgroundChildImpl;
class FileDescriptor;
class FileDescriptorSetChild final : public PFileDescriptorSetChild {
friend class BackgroundChildImpl;
friend class mozilla::dom::ContentChild;
friend class mozilla::net::SocketProcessChild;
friend class PFileDescriptorSetChild;
nsTArray<FileDescriptor> mFileDescriptors;
public:
void ForgetFileDescriptors(nsTArray<FileDescriptor>& aFileDescriptors);
private:
explicit FileDescriptorSetChild(const FileDescriptor& aFileDescriptor);
~FileDescriptorSetChild();
mozilla::ipc::IPCResult RecvAddFileDescriptor(
const FileDescriptor& aFileDescriptor);
};
} // namespace ipc
} // namespace mozilla
#endif // mozilla_ipc_FileDescriptorSetChild_h__

Просмотреть файл

@ -0,0 +1,33 @@
/* -*- 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 "FileDescriptorSetParent.h"
namespace mozilla::ipc {
FileDescriptorSetParent::FileDescriptorSetParent(
const FileDescriptor& aFileDescriptor) {
mFileDescriptors.AppendElement(aFileDescriptor);
}
FileDescriptorSetParent::~FileDescriptorSetParent() = default;
void FileDescriptorSetParent::ForgetFileDescriptors(
nsTArray<FileDescriptor>& aFileDescriptors) {
aFileDescriptors = std::move(mFileDescriptors);
}
void FileDescriptorSetParent::ActorDestroy(ActorDestroyReason aWhy) {
// Implement me! Bug 1005157
}
mozilla::ipc::IPCResult FileDescriptorSetParent::RecvAddFileDescriptor(
const FileDescriptor& aFileDescriptor) {
mFileDescriptors.AppendElement(aFileDescriptor);
return IPC_OK();
}
} // namespace mozilla::ipc

Просмотреть файл

@ -0,0 +1,58 @@
/* -*- 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_ipc_FileDescriptorSetParent_h__
#define mozilla_ipc_FileDescriptorSetParent_h__
#include "mozilla/Assertions.h"
#include "mozilla/Attributes.h"
#include "mozilla/ipc/PFileDescriptorSetParent.h"
#include "nsTArray.h"
namespace mozilla {
namespace dom {
class ContentParent;
} // namespace dom
namespace net {
class SocketProcessParent;
} // namespace net
namespace ipc {
class BackgroundParentImpl;
class FileDescriptor;
class FileDescriptorSetParent final : public PFileDescriptorSetParent {
friend class BackgroundParentImpl;
friend class mozilla::dom::ContentParent;
friend class mozilla::net::SocketProcessParent;
friend class PFileDescriptorSetParent;
nsTArray<FileDescriptor> mFileDescriptors;
public:
void ForgetFileDescriptors(nsTArray<FileDescriptor>& aFileDescriptors);
private:
explicit FileDescriptorSetParent(const FileDescriptor& aFileDescriptor);
~FileDescriptorSetParent();
virtual void ActorDestroy(ActorDestroyReason aWhy) override;
mozilla::ipc::IPCResult RecvAddFileDescriptor(
const FileDescriptor& aFileDescriptor);
};
} // namespace ipc
} // namespace mozilla
#endif // mozilla_ipc_FileDescriptorSetParent_h__

Просмотреть файл

@ -2,6 +2,10 @@
* 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 PChildToParentStream;
include protocol PParentToChildStream;
include BlobTypes;
include InputStreamParams;
include ProtocolTypes;
@ -9,13 +13,11 @@ namespace mozilla {
namespace ipc {
// Use IPCStream in your ipdl to represent serialized nsIInputStreams. Then use
// SerializeIPCStream from IPCStreamUtils.h to perform the serialization.
//
// NOTE: If you don't need to handle nsIInputStream serialization failure,
// `nsIInputStream` may be used directly by IPDL protocols.
// AutoIPCStream from IPCStreamUtils.h to perform the serialization.
struct IPCStream
{
InputStreamParams stream;
OptionalFileDescriptorSet optionalFds;
};
} // namespace ipc

23
ipc/glue/IPCStreamAlloc.h Normal file
Просмотреть файл

@ -0,0 +1,23 @@
/* -*- 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_ipc_IPCStreamAlloc_h
#define mozilla_ipc_IPCStreamAlloc_h
namespace mozilla {
namespace ipc {
class PChildToParentStreamParent;
class PParentToChildStreamChild;
PChildToParentStreamParent* AllocPChildToParentStreamParent();
PParentToChildStreamChild* AllocPParentToChildStreamChild();
} // namespace ipc
} // namespace mozilla
#endif // mozilla_ipc_IPCStreamAlloc_h

158
ipc/glue/IPCStreamChild.cpp Normal file
Просмотреть файл

@ -0,0 +1,158 @@
/* -*- 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 "IPCStreamDestination.h"
#include "IPCStreamSource.h"
#include "mozilla/Unused.h"
#include "mozilla/ipc/PChildToParentStreamChild.h"
#include "mozilla/ipc/PParentToChildStreamChild.h"
#include "mozilla/ipc/InputStreamUtils.h"
namespace mozilla {
namespace ipc {
// Child to Parent implementation
// ----------------------------------------------------------------------------
namespace {
class IPCStreamSourceChild final : public PChildToParentStreamChild,
public IPCStreamSource {
public:
static IPCStreamSourceChild* Create(nsIAsyncInputStream* aInputStream) {
MOZ_ASSERT(aInputStream);
IPCStreamSourceChild* source = new IPCStreamSourceChild(aInputStream);
if (!source->Initialize()) {
delete source;
return nullptr;
}
return source;
}
// PChildToParentStreamChild methods
void ActorDestroy(ActorDestroyReason aReason) override { ActorDestroyed(); }
IPCResult RecvStartReading() override {
Start();
return IPC_OK();
}
IPCResult RecvRequestClose(const nsresult& aRv) override {
OnEnd(aRv);
return IPC_OK();
}
void Close(nsresult aRv) override {
MOZ_ASSERT(IPCStreamSource::mState == IPCStreamSource::eClosed);
Unused << SendClose(aRv);
}
void SendData(const wr::ByteBuffer& aBuffer) override {
Unused << SendBuffer(aBuffer);
}
private:
explicit IPCStreamSourceChild(nsIAsyncInputStream* aInputStream)
: IPCStreamSource(aInputStream) {}
};
} // anonymous namespace
/* static */
PChildToParentStreamChild* IPCStreamSource::Create(
nsIAsyncInputStream* aInputStream,
ChildToParentStreamActorManager* aManager) {
MOZ_ASSERT(aInputStream);
MOZ_ASSERT(aManager);
IPCStreamSourceChild* source = IPCStreamSourceChild::Create(aInputStream);
if (!source) {
return nullptr;
}
if (!aManager->SendPChildToParentStreamConstructor(source)) {
return nullptr;
}
source->ActorConstructed();
return source;
}
/* static */
IPCStreamSource* IPCStreamSource::Cast(PChildToParentStreamChild* aActor) {
MOZ_ASSERT(aActor);
return static_cast<IPCStreamSourceChild*>(aActor);
}
// Parent to Child implementation
// ----------------------------------------------------------------------------
namespace {
class IPCStreamDestinationChild final : public PParentToChildStreamChild,
public IPCStreamDestination {
public:
nsresult Initialize() { return IPCStreamDestination::Initialize(); }
~IPCStreamDestinationChild() = default;
private:
// PParentToChildStreamChild methods
void ActorDestroy(ActorDestroyReason aReason) override { ActorDestroyed(); }
IPCResult RecvBuffer(const wr::ByteBuffer& aBuffer) override {
BufferReceived(aBuffer);
return IPC_OK();
}
IPCResult RecvClose(const nsresult& aRv) override {
CloseReceived(aRv);
return IPC_OK();
}
// IPCStreamDestination methods
void StartReading() override {
MOZ_ASSERT(HasDelayedStart());
Unused << SendStartReading();
}
void RequestClose(nsresult aRv) override { Unused << SendRequestClose(aRv); }
void TerminateDestination() override { Unused << Send__delete__(this); }
};
} // anonymous namespace
PParentToChildStreamChild* AllocPParentToChildStreamChild() {
IPCStreamDestinationChild* actor = new IPCStreamDestinationChild();
if (NS_WARN_IF(NS_FAILED(actor->Initialize()))) {
delete actor;
actor = nullptr;
}
return actor;
}
void DeallocPParentToChildStreamChild(PParentToChildStreamChild* aActor) {
delete aActor;
}
/* static */
IPCStreamDestination* IPCStreamDestination::Cast(
PParentToChildStreamChild* aActor) {
MOZ_ASSERT(aActor);
return static_cast<IPCStreamDestinationChild*>(aActor);
}
} // namespace ipc
} // namespace mozilla

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше