Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/dom/ipc/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 10 kB image not shown  

Quelle  StructuredCloneData.cpp   Sprache: C

 
/* -*- 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 "StructuredCloneData.h"

#include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/BlobBinding.h"
#include "mozilla/dom/BlobImpl.h"
#include "mozilla/dom/DOMTypes.h"
#include "mozilla/dom/File.h"
#include "mozilla/dom/IPCBlobUtils.h"
#include "mozilla/ipc/BackgroundParent.h"
#include "mozilla/ipc/IPCStreamUtils.h"
#include "mozilla/ipc/SerializedStructuredCloneBuffer.h"
#include "nsContentUtils.h"
#include "nsJSEnvironment.h"
#include "MainThreadUtils.h"
#include "StructuredCloneTags.h"
#include "jsapi.h"

using namespace mozilla::ipc;

namespace mozilla::dom::ipc {

using mozilla::ipc::IPCStream;
using mozilla::ipc::PBackgroundChild;
using mozilla::ipc::PBackgroundParent;

StructuredCloneData::StructuredCloneData()
    : StructuredCloneData(
          StructuredCloneHolder::StructuredCloneScope::DifferentProcess,
          StructuredCloneHolder::TransferringSupported) {}

StructuredCloneData::StructuredCloneData(StructuredCloneData&& aOther)
    : StructuredCloneData(
          StructuredCloneHolder::StructuredCloneScope::DifferentProcess,
          StructuredCloneHolder::TransferringSupported) {
  *this = std::move(aOther);
}

StructuredCloneData::StructuredCloneData(
    StructuredCloneHolder::StructuredCloneScope aScope,
    TransferringSupport aSupportsTransferring)
    : StructuredCloneHolder(StructuredCloneHolder::CloningSupported,
                            aSupportsTransferring, aScope),
      mExternalData(JS::StructuredCloneScope::DifferentProcess),
      mInitialized(false) {
  MOZ_ASSERT(
      aScope == StructuredCloneHolder::StructuredCloneScope::DifferentProcess ||
      aScope ==
          StructuredCloneHolder::StructuredCloneScope::UnknownDestination);
}

StructuredCloneData::~StructuredCloneData() = default;

StructuredCloneData& StructuredCloneData::operator=(
    StructuredCloneData&& aOther) {
  mBlobImplArray = std::move(aOther.mBlobImplArray);
  mExternalData = std::move(aOther.mExternalData);
  mSharedData = std::move(aOther.mSharedData);
  mPortIdentifiers = std::move(aOther.mPortIdentifiers);
  mInitialized = aOther.mInitialized;

  return *this;
}

bool StructuredCloneData::Copy(const StructuredCloneData& aData) {
  if (!aData.mInitialized) {
    return true;
  }

  if (aData.SharedData()) {
    mSharedData = aData.SharedData();
  } else {
    mSharedData = SharedJSAllocatedData::CreateFromExternalData(aData.Data());
    NS_ENSURE_TRUE(mSharedData, false);
  }

  if (mSupportsTransferring) {
    PortIdentifiers().AppendElements(aData.PortIdentifiers());
  }

  MOZ_ASSERT(BlobImpls().IsEmpty());
  BlobImpls().AppendElements(aData.BlobImpls());

  MOZ_ASSERT(GetSurfaces().IsEmpty());
  MOZ_ASSERT(WasmModules().IsEmpty());

  MOZ_ASSERT(InputStreams().IsEmpty());
  InputStreams().AppendElements(aData.InputStreams());

  mInitialized = true;

  return true;
}

void StructuredCloneData::Read(JSContext* aCx,
                               JS::MutableHandle<JS::Value> aValue,
                               ErrorResult& aRv) {
  Read(aCx, aValue, JS::CloneDataPolicy(), aRv);
}

void StructuredCloneData::Read(JSContext* aCx,
                               JS::MutableHandle<JS::Value> aValue,
                               const JS::CloneDataPolicy& aCloneDataPolicy,
                               ErrorResult& aRv) {
  MOZ_ASSERT(mInitialized);

  nsIGlobalObject* global = xpc::CurrentNativeGlobal(aCx);
  MOZ_ASSERT(global);

  ReadFromBuffer(global, aCx, Data(), aValue, aCloneDataPolicy, aRv);
}

void StructuredCloneData::Write(JSContext* aCx, JS::Handle<JS::Value> aValue,
                                ErrorResult& aRv) {
  Write(aCx, aValue, JS::UndefinedHandleValue, JS::CloneDataPolicy(), aRv);
}

void StructuredCloneData::Write(JSContext* aCx, JS::Handle<JS::Value> aValue,
                                JS::Handle<JS::Value> aTransfer,
                                const JS::CloneDataPolicy& aCloneDataPolicy,
                                ErrorResult& aRv) {
  MOZ_ASSERT(!mInitialized);

  StructuredCloneHolder::Write(aCx, aValue, aTransfer, aCloneDataPolicy, aRv);
  if (NS_WARN_IF(aRv.Failed())) {
    return;
  }

  JSStructuredCloneData data(mBuffer->scope());
  mBuffer->giveTo(&data);
  mBuffer = nullptr;
  mSharedData = new SharedJSAllocatedData(std::move(data));
  mInitialized = true;
}

bool StructuredCloneData::BuildClonedMessageData(
    ClonedMessageData& aClonedData) {
  SerializedStructuredCloneBuffer& buffer = aClonedData.data();
  auto iter = Data().Start();
  size_t size = Data().Size();
  bool success;
  buffer.data = Data().Borrow(iter, size, &success);
  if (NS_WARN_IF(!success)) {
    return false;
  }
  if (SupportsTransferring()) {
    aClonedData.identifiers().AppendElements(PortIdentifiers());
  }

  const nsTArray<RefPtr<BlobImpl>>& blobImpls = BlobImpls();

  if (!blobImpls.IsEmpty()) {
    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], aClonedData.blobs()[i]);
      if (NS_WARN_IF(NS_FAILED(rv))) {
        return false;
      }
    }
  }

  const nsTArray<nsCOMPtr<nsIInputStream>>& inputStreams = InputStreams();
  if (!inputStreams.IsEmpty()) {
    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)) {
        return false;
      }
      streams.AppendElement(value);
    }
  }

  return true;
}

// See the StructuredCloneData class block comment for the meanings of each val.
enum MemoryFlavorEnum { BorrowMemory = 0, CopyMemory, StealMemory };

template <MemoryFlavorEnum>
struct MemoryTraits {};

template <>
struct MemoryTraits<BorrowMemory> {
  using ClonedMessageType = const mozilla::dom::ClonedMessageData;

  static void ProvideBuffer(const ClonedMessageData& aClonedData,
                            StructuredCloneData& aData) {
    const SerializedStructuredCloneBuffer& buffer = aClonedData.data();
    aData.UseExternalData(buffer.data);
  }
};

template <>
struct MemoryTraits<CopyMemory> {
  using ClonedMessageType = const mozilla::dom::ClonedMessageData;

  static void ProvideBuffer(const ClonedMessageData& aClonedData,
                            StructuredCloneData& aData) {
    const SerializedStructuredCloneBuffer& buffer = aClonedData.data();
    aData.CopyExternalData(buffer.data);
  }
};

template <>
struct MemoryTraits<StealMemory> {
  // note: not const!
  using ClonedMessageType = mozilla::dom::ClonedMessageData;

  static void ProvideBuffer(ClonedMessageData& aClonedData,
                            StructuredCloneData& aData) {
    SerializedStructuredCloneBuffer& buffer = aClonedData.data();
    aData.StealExternalData(buffer.data);
  }
};

// Note that there isn't actually a difference between Parent/BackgroundParent
// and Child/BackgroundChild in this implementation.  The calling methods,
// however, do maintain the distinction for code-reading purposes and are backed
// by assertions to enforce there is no misuse.
template <MemoryFlavorEnum MemoryFlavor>
static void UnpackClonedMessageData(
    typename MemoryTraits<MemoryFlavor>::ClonedMessageType& aClonedData,
    StructuredCloneData& aData) {
  const nsTArray<MessagePortIdentifier>& identifiers =
      aClonedData.identifiers();

  MemoryTraits<MemoryFlavor>::ProvideBuffer(aClonedData, aData);

  if (aData.SupportsTransferring()) {
    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) {
      RefPtr<BlobImpl> blobImpl = IPCBlobUtils::Deserialize(blobs[i]);
      MOZ_ASSERT(blobImpl);

      aData.BlobImpls().AppendElement(blobImpl);
    }
  }

  const nsTArray<IPCStream>& streams = aClonedData.inputStreams();
  if (!streams.IsEmpty()) {
    uint32_t length = streams.Length();
    aData.InputStreams().SetCapacity(length);
    for (uint32_t i = 0; i < length; ++i) {
      nsCOMPtr<nsIInputStream> stream = DeserializeIPCStream(streams[i]);
      aData.InputStreams().AppendElement(stream);
    }
  }
}

void StructuredCloneData::BorrowFromClonedMessageData(
    const ClonedMessageData& aClonedData) {
  UnpackClonedMessageData<BorrowMemory>(aClonedData, *this);
}

void StructuredCloneData::CopyFromClonedMessageData(
    const ClonedMessageData& aClonedData) {
  UnpackClonedMessageData<CopyMemory>(aClonedData, *this);
}

void StructuredCloneData::StealFromClonedMessageData(
    ClonedMessageData& aClonedData) {
  UnpackClonedMessageData<StealMemory>(aClonedData, *this);
}

void StructuredCloneData::WriteIPCParams(IPC::MessageWriter* aWriter) const {
  WriteParam(aWriter, Data());
}

bool StructuredCloneData::ReadIPCParams(IPC::MessageReader* aReader) {
  MOZ_ASSERT(!mInitialized);
  JSStructuredCloneData data(JS::StructuredCloneScope::DifferentProcess);
  if (!ReadParam(aReader, &data)) {
    return false;
  }
  mSharedData = new SharedJSAllocatedData(std::move(data));
  mInitialized = true;
  return true;
}

bool StructuredCloneData::CopyExternalData(const char* aData,
                                           size_t aDataLength) {
  MOZ_ASSERT(!mInitialized);
  mSharedData =
      SharedJSAllocatedData::CreateFromExternalData(aData, aDataLength);
  NS_ENSURE_TRUE(mSharedData, false);
  mInitialized = true;
  return true;
}

bool StructuredCloneData::CopyExternalData(const JSStructuredCloneData& aData) {
  MOZ_ASSERT(!mInitialized);
  mSharedData = SharedJSAllocatedData::CreateFromExternalData(aData);
  NS_ENSURE_TRUE(mSharedData, false);
  mInitialized = true;
  return true;
}

bool StructuredCloneData::StealExternalData(JSStructuredCloneData& aData) {
  MOZ_ASSERT(!mInitialized);
  mSharedData = new SharedJSAllocatedData(std::move(aData));
  mInitialized = true;
  return true;
}

already_AddRefed<SharedJSAllocatedData> StructuredCloneData::TakeSharedData() {
  return mSharedData.forget();
}

}  // namespace mozilla::dom::ipc

Messung V0.5
C=91 H=98 G=94

¤ Dauer der Verarbeitung: 0.15 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.