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 "BroadcastChannelService.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/IPCStreamUtils.h"
#include "mozilla/Unused.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 mozilla

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

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

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

@ -7,7 +7,7 @@
#include "BroadcastChannelService.h"
#include "BroadcastChannelParent.h"
#include "mozilla/dom/File.h"
#include "mozilla/dom/ipc/BlobParent.h"
#include "mozilla/dom/IPCBlobUtils.h"
#include "mozilla/ipc/BackgroundParent.h"
#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.
nsTArray<RefPtr<BlobImpl>> blobs;
if (!aData.blobsParent().IsEmpty()) {
blobs.SetCapacity(aData.blobsParent().Length());
nsTArray<RefPtr<BlobImpl>> blobImpls;
if (!aData.blobs().IsEmpty()) {
blobImpls.SetCapacity(aData.blobs().Length());
for (uint32_t i = 0, len = aData.blobsParent().Length(); i < len; ++i) {
RefPtr<BlobImpl> impl =
static_cast<BlobParent*>(aData.blobsParent()[i])->GetBlobImpl();
MOZ_ASSERT(impl);
blobs.AppendElement(impl);
for (uint32_t i = 0, len = aData.blobs().Length(); i < len; ++i) {
RefPtr<BlobImpl> impl = IPCBlobUtils::Deserialize(aData.blobs()[i]);
MOZ_ASSERT(impl);
blobImpls.AppendElement(impl);
}
}
// For each parent actor, we notify the message.
for (uint32_t i = 0; i < parents->Length(); ++i) {
BroadcastChannelParent* parent = parents->ElementAt(i);
MOZ_ASSERT(parent);
if (parent != aParent) {
parent->Deliver(aData);
if (parent == aParent) {
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 PMemoryStream;
include IPCBlob;
include IPCStream;
include ProtocolTypes;
@ -41,7 +42,7 @@ struct MessagePortIdentifier
struct ClonedMessageData
{
SerializedStructuredCloneBuffer data;
PBlob[] blobs;
IPCBlob[] blobs;
IPCStream[] inputStreams;
MessagePortIdentifier[] identfiers;
};

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

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

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

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

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

@ -203,8 +203,8 @@ public:
// Actor-varying methods to convert the structured clone stored in this holder
// 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
// able to create them.)
// (Blobs are represented in IPC by IPCBlob actors, so we need the parent to
// be able to create them.)
bool BuildClonedMessageDataForParent(nsIContentParent* aParent,
ClonedMessageData& aClonedData);
bool BuildClonedMessageDataForChild(nsIContentChild* aChild,