зеркало из https://github.com/mozilla/gecko-dev.git
Backed out 22 changesets (bug 1759572, bug 1759563, bug 1754004, bug 1754031, bug 1759569, bug 1696894) for causing multiple failures CLOSED TREE
Backed out changeset d69647a725a1 (bug 1754004) Backed out changeset 09fc506865d7 (bug 1754004) Backed out changeset 648e3dd4b62f (bug 1754004) Backed out changeset 3465158ee230 (bug 1696894) Backed out changeset b08475bbfbd9 (bug 1754004) Backed out changeset dfabce587a56 (bug 1754004) Backed out changeset cebe8d5dda34 (bug 1754004) Backed out changeset 55b4b0c9a504 (bug 1754004) Backed out changeset e8649de9dd22 (bug 1754004) Backed out changeset 0f480fc861c0 (bug 1754004) Backed out changeset e515b7edd1c8 (bug 1754004) Backed out changeset fe90db9158ac (bug 1754004) Backed out changeset c6388d682d48 (bug 1754004) Backed out changeset 2374420d9fed (bug 1754004) Backed out changeset 44dfd76472aa (bug 1754004) Backed out changeset 000fb99de0cf (bug 1754004) Backed out changeset 0ca1856b5fc9 (bug 1754004) Backed out changeset 10c3683b998b (bug 1754004) Backed out changeset 4abc98ed6b99 (bug 1759572) Backed out changeset cdd271a5af42 (bug 1759563) Backed out changeset fadb6cc0d81c (bug 1759569) Backed out changeset 44be9709a93e (bug 1754031)
This commit is contained in:
Родитель
132677828f
Коммит
39469989c9
|
@ -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;
|
||||
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
|
|
|
@ -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,6 +13,9 @@
|
|||
#include "nsTObserverArray.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace ipc {
|
||||
class AutoIPCStream;
|
||||
} // namespace ipc
|
||||
namespace dom {
|
||||
namespace cache {
|
||||
|
||||
|
@ -33,7 +36,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;
|
||||
|
|
|
@ -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,6 +13,9 @@
|
|||
#include "nsTObserverArray.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace ipc {
|
||||
class AutoIPCStream;
|
||||
} // namespace ipc
|
||||
namespace dom {
|
||||
namespace cache {
|
||||
|
||||
|
@ -35,7 +38,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;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
include protocol PCache;
|
||||
include protocol PCacheStreamControl;
|
||||
include protocol PChildToParentStream;
|
||||
include IPCStream;
|
||||
include IPCChannelInfo;
|
||||
include PBackgroundSharedTypes;
|
||||
|
|
|
@ -5,6 +5,9 @@
|
|||
include protocol PBackground;
|
||||
include protocol PCacheOp;
|
||||
include protocol PCacheStreamControl;
|
||||
include protocol PFileDescriptorSet;
|
||||
include protocol PChildToParentStream;
|
||||
include protocol PParentToChildStream;
|
||||
|
||||
include CacheTypes;
|
||||
|
||||
|
|
|
@ -5,6 +5,9 @@
|
|||
include protocol PCache;
|
||||
include protocol PCacheStorage;
|
||||
include protocol PCacheStreamControl;
|
||||
include protocol PFileDescriptorSet;
|
||||
include protocol PChildToParentStream;
|
||||
include protocol PParentToChildStream;
|
||||
|
||||
include CacheTypes;
|
||||
|
||||
|
|
|
@ -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,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";
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -19,6 +19,9 @@
|
|||
namespace mozilla {
|
||||
class ErrorResult;
|
||||
|
||||
namespace ipc {
|
||||
class AutoIPCStream;
|
||||
} // namespace ipc
|
||||
namespace dom {
|
||||
namespace cache {
|
||||
|
||||
|
@ -75,8 +78,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;
|
||||
|
|
|
@ -15,6 +15,9 @@
|
|||
struct nsID;
|
||||
|
||||
namespace mozilla {
|
||||
namespace ipc {
|
||||
class AutoIPCStream;
|
||||
} // namespace ipc
|
||||
namespace dom {
|
||||
namespace cache {
|
||||
|
||||
|
@ -28,8 +31,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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
||||
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() = 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);
|
||||
|
|
|
@ -2064,7 +2064,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));
|
||||
|
@ -2233,13 +2232,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
|
||||
|
|
|
@ -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
|
|
@ -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
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче