Bug 1353629 - PBlob refactoring - part 3 - IPCBlob in ClonedMessageData, r=smaug

This is the first use of IPCBlob: ClonedMessageData.
ClonedMessageData is used for BroadcastChannel, MessagePort and any
postMessage() communication. This patch changes StructuredCloneData in order to
use IPCBlob instead of PBlob.
BroadcastChannel has a custom way to manage Blobs because when the parent
receives them from a content process, it must send them to any other
BroadcastChild actor duplicating the serialization.
This commit is contained in:
Andrea Marchesini 2017-04-20 15:20:38 +02:00
Родитель 189f9f2cca
Коммит b42d5af54d
7 изменённых файлов: 60 добавлений и 150 удалений

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

@ -7,8 +7,9 @@
#include "BroadcastChannelParent.h" #include "BroadcastChannelParent.h"
#include "BroadcastChannelService.h" #include "BroadcastChannelService.h"
#include "mozilla/dom/File.h" #include "mozilla/dom/File.h"
#include "mozilla/dom/ipc/BlobParent.h" #include "mozilla/dom/IPCBlobUtils.h"
#include "mozilla/ipc/BackgroundParent.h" #include "mozilla/ipc/BackgroundParent.h"
#include "mozilla/ipc/IPCStreamUtils.h"
#include "mozilla/Unused.h" #include "mozilla/Unused.h"
#include "nsIScriptSecurityManager.h" #include "nsIScriptSecurityManager.h"
@ -73,30 +74,5 @@ BroadcastChannelParent::ActorDestroy(ActorDestroyReason aWhy)
} }
} }
void
BroadcastChannelParent::Deliver(const ClonedMessageData& aData)
{
AssertIsOnBackgroundThread();
// Duplicate the data for this parent.
ClonedMessageData newData(aData);
// Create new BlobParent objects for this message.
for (uint32_t i = 0, len = newData.blobsParent().Length(); i < len; ++i) {
RefPtr<BlobImpl> impl =
static_cast<BlobParent*>(newData.blobsParent()[i])->GetBlobImpl();
PBlobParent* blobParent =
BackgroundParent::GetOrCreateActorForBlobImpl(Manager(), impl);
if (!blobParent) {
return;
}
newData.blobsParent()[i] = blobParent;
}
Unused << SendNotify(newData);
}
} // namespace dom } // namespace dom
} // namespace mozilla } // namespace mozilla

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

@ -26,9 +26,6 @@ class BroadcastChannelParent final : public PBroadcastChannelParent
typedef mozilla::ipc::PrincipalInfo PrincipalInfo; typedef mozilla::ipc::PrincipalInfo PrincipalInfo;
public:
void Deliver(const ClonedMessageData& aData);
private: private:
explicit BroadcastChannelParent(const nsAString& aOriginChannelKey); explicit BroadcastChannelParent(const nsAString& aOriginChannelKey);
~BroadcastChannelParent(); ~BroadcastChannelParent();

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

@ -7,7 +7,7 @@
#include "BroadcastChannelService.h" #include "BroadcastChannelService.h"
#include "BroadcastChannelParent.h" #include "BroadcastChannelParent.h"
#include "mozilla/dom/File.h" #include "mozilla/dom/File.h"
#include "mozilla/dom/ipc/BlobParent.h" #include "mozilla/dom/IPCBlobUtils.h"
#include "mozilla/ipc/BackgroundParent.h" #include "mozilla/ipc/BackgroundParent.h"
#ifdef XP_WIN #ifdef XP_WIN
@ -106,25 +106,43 @@ BroadcastChannelService::PostMessage(BroadcastChannelParent* aParent,
} }
// We need to keep the array alive for the life-time of this operation. // We need to keep the array alive for the life-time of this operation.
nsTArray<RefPtr<BlobImpl>> blobs; nsTArray<RefPtr<BlobImpl>> blobImpls;
if (!aData.blobsParent().IsEmpty()) { if (!aData.blobs().IsEmpty()) {
blobs.SetCapacity(aData.blobsParent().Length()); blobImpls.SetCapacity(aData.blobs().Length());
for (uint32_t i = 0, len = aData.blobsParent().Length(); i < len; ++i) { for (uint32_t i = 0, len = aData.blobs().Length(); i < len; ++i) {
RefPtr<BlobImpl> impl = RefPtr<BlobImpl> impl = IPCBlobUtils::Deserialize(aData.blobs()[i]);
static_cast<BlobParent*>(aData.blobsParent()[i])->GetBlobImpl();
MOZ_ASSERT(impl); MOZ_ASSERT(impl);
blobs.AppendElement(impl); blobImpls.AppendElement(impl);
} }
} }
// For each parent actor, we notify the message.
for (uint32_t i = 0; i < parents->Length(); ++i) { for (uint32_t i = 0; i < parents->Length(); ++i) {
BroadcastChannelParent* parent = parents->ElementAt(i); BroadcastChannelParent* parent = parents->ElementAt(i);
MOZ_ASSERT(parent); MOZ_ASSERT(parent);
if (parent != aParent) { if (parent == aParent) {
parent->Deliver(aData); continue;
} }
// We need to have a copy of the data for this parent.
ClonedMessageData newData(aData);
MOZ_ASSERT(blobImpls.Length() == newData.blobs().Length());
if (!blobImpls.IsEmpty()) {
// Serialize Blob objects for this message.
for (uint32_t i = 0, len = blobImpls.Length(); i < len; ++i) {
nsresult rv = IPCBlobUtils::Serialize(blobImpls[i], parent->Manager(),
newData.blobs()[i]);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
}
}
Unused << parent->SendNotify(newData);
} }
} }

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

@ -7,6 +7,7 @@
include protocol PBlob; include protocol PBlob;
include protocol PMemoryStream; include protocol PMemoryStream;
include IPCBlob;
include IPCStream; include IPCStream;
include ProtocolTypes; include ProtocolTypes;
@ -41,7 +42,7 @@ struct MessagePortIdentifier
struct ClonedMessageData struct ClonedMessageData
{ {
SerializedStructuredCloneBuffer data; SerializedStructuredCloneBuffer data;
PBlob[] blobs; IPCBlob[] blobs;
IPCStream[] inputStreams; IPCStream[] inputStreams;
MessagePortIdentifier[] identfiers; MessagePortIdentifier[] identfiers;
}; };

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

@ -20,6 +20,8 @@ include protocol PChildToParentStream;
include protocol PParentToChildStream; include protocol PParentToChildStream;
include protocol PFileDescriptorSet; include protocol PFileDescriptorSet;
include DOMTypes; include DOMTypes;
include IPCBlob;
include IPCStream;
include JavaScriptTypes; include JavaScriptTypes;
include URIParams; include URIParams;
include PPrintingTypes; include PPrintingTypes;

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

@ -13,6 +13,7 @@
#include "ipc/IPCMessageUtils.h" #include "ipc/IPCMessageUtils.h"
#include "mozilla/dom/BindingUtils.h" #include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/BlobBinding.h" #include "mozilla/dom/BlobBinding.h"
#include "mozilla/dom/IPCBlobUtils.h"
#include "mozilla/dom/File.h" #include "mozilla/dom/File.h"
#include "mozilla/ipc/IPCStreamUtils.h" #include "mozilla/ipc/IPCStreamUtils.h"
#include "nsContentUtils.h" #include "nsContentUtils.h"
@ -142,92 +143,9 @@ enum ManagerFlavorEnum {
BackgroundProtocol BackgroundProtocol
}; };
template <ActorFlavorEnum> template<typename M>
struct BlobTraits bool
{ }; BuildClonedMessageData(M* aManager, StructuredCloneData& aData,
template <>
struct BlobTraits<Parent>
{
typedef mozilla::dom::BlobParent BlobType;
typedef mozilla::dom::PBlobParent ProtocolType;
};
template <>
struct BlobTraits<Child>
{
typedef mozilla::dom::BlobChild BlobType;
typedef mozilla::dom::PBlobChild ProtocolType;
};
template <ActorFlavorEnum, ManagerFlavorEnum>
struct ParentManagerTraits
{ };
template<>
struct ParentManagerTraits<Parent, ContentProtocol>
{
typedef mozilla::dom::nsIContentParent ConcreteContentManagerType;
};
template<>
struct ParentManagerTraits<Child, ContentProtocol>
{
typedef mozilla::dom::nsIContentChild ConcreteContentManagerType;
};
template<>
struct ParentManagerTraits<Parent, BackgroundProtocol>
{
typedef mozilla::ipc::PBackgroundParent ConcreteContentManagerType;
};
template<>
struct ParentManagerTraits<Child, BackgroundProtocol>
{
typedef mozilla::ipc::PBackgroundChild ConcreteContentManagerType;
};
template<ActorFlavorEnum>
struct DataBlobs
{ };
template<>
struct DataBlobs<Parent>
{
typedef BlobTraits<Parent>::ProtocolType ProtocolType;
static InfallibleTArray<ProtocolType*>& Blobs(ClonedMessageData& aData)
{
return aData.blobsParent();
}
static const InfallibleTArray<ProtocolType*>& Blobs(const ClonedMessageData& aData)
{
return aData.blobsParent();
}
};
template<>
struct DataBlobs<Child>
{
typedef BlobTraits<Child>::ProtocolType ProtocolType;
static InfallibleTArray<ProtocolType*>& Blobs(ClonedMessageData& aData)
{
return aData.blobsChild();
}
static const InfallibleTArray<ProtocolType*>& Blobs(const ClonedMessageData& aData)
{
return aData.blobsChild();
}
};
template<ActorFlavorEnum Flavor, ManagerFlavorEnum ManagerFlavor>
static bool
BuildClonedMessageData(typename ParentManagerTraits<Flavor, ManagerFlavor>::ConcreteContentManagerType* aManager,
StructuredCloneData& aData,
ClonedMessageData& aClonedData) ClonedMessageData& aClonedData)
{ {
SerializedStructuredCloneBuffer& buffer = aClonedData.data(); SerializedStructuredCloneBuffer& buffer = aClonedData.data();
@ -245,23 +163,26 @@ BuildClonedMessageData(typename ParentManagerTraits<Flavor, ManagerFlavor>::Conc
const nsTArray<RefPtr<BlobImpl>>& blobImpls = aData.BlobImpls(); const nsTArray<RefPtr<BlobImpl>>& blobImpls = aData.BlobImpls();
if (!blobImpls.IsEmpty()) { if (!blobImpls.IsEmpty()) {
typedef typename BlobTraits<Flavor>::BlobType BlobType; if (NS_WARN_IF(!aClonedData.blobs().SetLength(blobImpls.Length(), fallible))) {
typedef typename BlobTraits<Flavor>::ProtocolType ProtocolType; return false;
InfallibleTArray<ProtocolType*>& blobList = DataBlobs<Flavor>::Blobs(aClonedData); }
uint32_t length = blobImpls.Length();
blobList.SetCapacity(length); for (uint32_t i = 0; i < blobImpls.Length(); ++i) {
for (uint32_t i = 0; i < length; ++i) { nsresult rv = IPCBlobUtils::Serialize(blobImpls[i], aManager,
BlobType* protocolActor = BlobType::GetOrCreate(aManager, blobImpls[i]); aClonedData.blobs()[i]);
if (!protocolActor) { if (NS_WARN_IF(NS_FAILED(rv))) {
return false; return false;
} }
blobList.AppendElement(protocolActor);
} }
} }
const nsTArray<nsCOMPtr<nsIInputStream>>& inputStreams = aData.InputStreams(); const nsTArray<nsCOMPtr<nsIInputStream>>& inputStreams = aData.InputStreams();
if (!inputStreams.IsEmpty()) { if (!inputStreams.IsEmpty()) {
if (NS_WARN_IF(!aData.IPCStreams().SetCapacity(inputStreams.Length(),
fallible))) {
return false;
}
InfallibleTArray<IPCStream>& streams = aClonedData.inputStreams(); InfallibleTArray<IPCStream>& streams = aClonedData.inputStreams();
uint32_t length = inputStreams.Length(); uint32_t length = inputStreams.Length();
streams.SetCapacity(length); streams.SetCapacity(length);
@ -286,7 +207,7 @@ StructuredCloneData::BuildClonedMessageDataForParent(
nsIContentParent* aParent, nsIContentParent* aParent,
ClonedMessageData& aClonedData) ClonedMessageData& aClonedData)
{ {
return BuildClonedMessageData<Parent, ContentProtocol>(aParent, *this, aClonedData); return BuildClonedMessageData(aParent, *this, aClonedData);
} }
bool bool
@ -294,7 +215,7 @@ StructuredCloneData::BuildClonedMessageDataForChild(
nsIContentChild* aChild, nsIContentChild* aChild,
ClonedMessageData& aClonedData) ClonedMessageData& aClonedData)
{ {
return BuildClonedMessageData<Child, ContentProtocol>(aChild, *this, aClonedData); return BuildClonedMessageData(aChild, *this, aClonedData);
} }
bool bool
@ -302,7 +223,7 @@ StructuredCloneData::BuildClonedMessageDataForBackgroundParent(
PBackgroundParent* aParent, PBackgroundParent* aParent,
ClonedMessageData& aClonedData) ClonedMessageData& aClonedData)
{ {
return BuildClonedMessageData<Parent, BackgroundProtocol>(aParent, *this, aClonedData); return BuildClonedMessageData(aParent, *this, aClonedData);
} }
bool bool
@ -310,7 +231,7 @@ StructuredCloneData::BuildClonedMessageDataForBackgroundChild(
PBackgroundChild* aChild, PBackgroundChild* aChild,
ClonedMessageData& aClonedData) ClonedMessageData& aClonedData)
{ {
return BuildClonedMessageData<Child, BackgroundProtocol>(aChild, *this, aClonedData); return BuildClonedMessageData(aChild, *this, aClonedData);
} }
// See the StructuredCloneData class block comment for the meanings of each val. // See the StructuredCloneData class block comment for the meanings of each val.
@ -373,8 +294,6 @@ static void
UnpackClonedMessageData(typename MemoryTraits<MemoryFlavor>::ClonedMessageType& aClonedData, UnpackClonedMessageData(typename MemoryTraits<MemoryFlavor>::ClonedMessageType& aClonedData,
StructuredCloneData& aData) StructuredCloneData& aData)
{ {
typedef typename BlobTraits<Flavor>::ProtocolType ProtocolType;
const InfallibleTArray<ProtocolType*>& blobs = DataBlobs<Flavor>::Blobs(aClonedData);
const InfallibleTArray<MessagePortIdentifier>& identifiers = aClonedData.identfiers(); const InfallibleTArray<MessagePortIdentifier>& identifiers = aClonedData.identfiers();
MemoryTraits<MemoryFlavor>::ProvideBuffer(aClonedData, aData); MemoryTraits<MemoryFlavor>::ProvideBuffer(aClonedData, aData);
@ -383,15 +302,12 @@ UnpackClonedMessageData(typename MemoryTraits<MemoryFlavor>::ClonedMessageType&
aData.PortIdentifiers().AppendElements(identifiers); aData.PortIdentifiers().AppendElements(identifiers);
} }
const nsTArray<IPCBlob>& blobs = aClonedData.blobs();
if (!blobs.IsEmpty()) { if (!blobs.IsEmpty()) {
uint32_t length = blobs.Length(); uint32_t length = blobs.Length();
aData.BlobImpls().SetCapacity(length); aData.BlobImpls().SetCapacity(length);
for (uint32_t i = 0; i < length; ++i) { for (uint32_t i = 0; i < length; ++i) {
auto* blob = RefPtr<BlobImpl> blobImpl = IPCBlobUtils::Deserialize(blobs[i]);
static_cast<typename BlobTraits<Flavor>::BlobType*>(blobs[i]);
MOZ_ASSERT(blob);
RefPtr<BlobImpl> blobImpl = blob->GetBlobImpl();
MOZ_ASSERT(blobImpl); MOZ_ASSERT(blobImpl);
aData.BlobImpls().AppendElement(blobImpl); aData.BlobImpls().AppendElement(blobImpl);

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

@ -203,8 +203,8 @@ public:
// Actor-varying methods to convert the structured clone stored in this holder // Actor-varying methods to convert the structured clone stored in this holder
// by a previous call to Write() into ClonedMessageData IPC representation. // by a previous call to Write() into ClonedMessageData IPC representation.
// (Blobs are represented in IPC by PBlob actors, so we need the parent to be // (Blobs are represented in IPC by IPCBlob actors, so we need the parent to
// able to create them.) // be able to create them.)
bool BuildClonedMessageDataForParent(nsIContentParent* aParent, bool BuildClonedMessageDataForParent(nsIContentParent* aParent,
ClonedMessageData& aClonedData); ClonedMessageData& aClonedData);
bool BuildClonedMessageDataForChild(nsIContentChild* aChild, bool BuildClonedMessageDataForChild(nsIContentChild* aChild,