/* 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 "StructuredCloneData.h" #include "ipc/IPCMessageUtilsSpecializations.h" #include "mozilla/dom/BlobImpl.h" #include "mozilla/dom/DOMTypes.h" #include "mozilla/dom/IPCBlobUtils.h" #include "mozilla/ipc/SerializedStructuredCloneBuffer.h" #include "nsContentUtils.h" using namespace mozilla::ipc; namespace mozilla::dom::ipc { StructuredCloneData::StructuredCloneData() : StructuredCloneData(StructuredCloneScope::DifferentProcess, StructuredCloneHolder::TransferringSupported) {} StructuredCloneData::StructuredCloneData( StructuredCloneScope aScope, TransferringSupport aSupportsTransferring) : StructuredCloneHolder(StructuredCloneHolder::CloningSupported, aSupportsTransferring, aScope) { MOZ_ASSERT(aScope == StructuredCloneScope::DifferentProcess || aScope == StructuredCloneScope::UnknownDestination); } StructuredCloneData::~StructuredCloneData() = default; void StructuredCloneData::WriteIPCParams(IPC::MessageWriter* aWriter) { MOZ_RELEASE_ASSERT( CloneScope() == StructuredCloneScope::DifferentProcess, "Cannot serialize same-process StructuredCloneData over IPC"); AssertAttachmentsMatchFlags(); WriteParam(aWriter, BufferVersion()); WriteParam(aWriter, BufferData()); // Write all cloneable attachments directly to IPC. std::apply([&](auto&... member) { WriteParams(aWriter, member...); }, CloneableAttachmentArrays()); // Also write all transferable members, if we support transferring. if (SupportsTransferring()) { std::apply([&](auto&... member) { WriteParams(aWriter, member...); }, TransferableAttachmentArrays()); } } bool StructuredCloneData::ReadIPCParams(IPC::MessageReader* aReader) { MOZ_ASSERT(!mBuffer, "StructuredCloneData was previously initialized"); GeckoChildID originChildID = aReader->GetActor() ? aReader->GetActor()->ToplevelProtocol()->OtherChildIDMaybeInvalid() : kInvalidGeckoChildID; uint32_t version; JSStructuredCloneData data(JS::StructuredCloneScope::DifferentProcess); if (!ReadParam(aReader, &version) || !ReadParam(aReader, &data)) { return false; } Adopt(std::move(data), version, originChildID); if (!std::apply( [&](auto&... member) { return ReadParams(aReader, member...); }, CloneableAttachmentArrays())) { return false; } if (SupportsTransferring()) { if (!std::apply( [&](auto&... member) { return ReadParams(aReader, member...); }, TransferableAttachmentArrays())) { return false; } } AssertAttachmentsMatchFlags(); return true; } bool StructuredCloneData::CopyExternalData(const char* aData, size_t aDataLength, uint32_t aVersion) { MOZ_ASSERT(!mBuffer, "StructuredCloneData was previously initialized"); JSStructuredCloneData data(JS::StructuredCloneScope::DifferentProcess); if (!data.AppendBytes(aData, aDataLength)) { return false; } Adopt(std::move(data), aVersion); return true; } } // namespace mozilla::dom::ipc void IPC::ParamTraits::Write( MessageWriter* aWriter, paramType* aParam) { WriteParam(aWriter, aParam != nullptr); if (aParam) { WriteParam(aWriter, aParam->SupportsTransferring()); aParam->WriteIPCParams(aWriter); } } bool IPC::ParamTraits::Read( MessageReader* aReader, RefPtr* aResult) { bool notNull = false; if (!ReadParam(aReader, ¬Null)) { return false; } if (notNull) { bool supportsTransferring; if (!ReadParam(aReader, &supportsTransferring)) { return false; } *aResult = mozilla::MakeRefPtr( JS::StructuredCloneScope::DifferentProcess, supportsTransferring ? mozilla::dom::StructuredCloneHolder::TransferringSupported : mozilla::dom::StructuredCloneHolder::TransferringNotSupported); return (*aResult)->ReadIPCParams(aReader); } return true; }