summaryrefslogtreecommitdiffstats
path: root/ipc/glue/SerializedStructuredCloneBuffer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ipc/glue/SerializedStructuredCloneBuffer.cpp')
-rw-r--r--ipc/glue/SerializedStructuredCloneBuffer.cpp79
1 files changed, 79 insertions, 0 deletions
diff --git a/ipc/glue/SerializedStructuredCloneBuffer.cpp b/ipc/glue/SerializedStructuredCloneBuffer.cpp
new file mode 100644
index 0000000000..9cad1ed826
--- /dev/null
+++ b/ipc/glue/SerializedStructuredCloneBuffer.cpp
@@ -0,0 +1,79 @@
+/* -*- 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 "mozilla/ipc/SerializedStructuredCloneBuffer.h"
+#include "js/StructuredClone.h"
+
+namespace IPC {
+
+void ParamTraits<JSStructuredCloneData>::Write(MessageWriter* aWriter,
+ const paramType& aParam) {
+ MOZ_ASSERT(!(aParam.Size() % sizeof(uint64_t)));
+
+ // We can only construct shared memory regions up to 4Gb in size, making that
+ // the maximum possible JSStructuredCloneData size.
+ mozilla::CheckedUint32 size = aParam.Size();
+ if (!size.isValid()) {
+ aWriter->FatalError("JSStructuredCloneData over 4Gb in size");
+ return;
+ }
+ WriteParam(aWriter, size.value());
+
+ MessageBufferWriter bufWriter(aWriter, size.value());
+ aParam.ForEachDataChunk([&](const char* aData, size_t aSize) {
+ return bufWriter.WriteBytes(aData, aSize);
+ });
+}
+
+bool ParamTraits<JSStructuredCloneData>::Read(MessageReader* aReader,
+ paramType* aResult) {
+ uint32_t length = 0;
+ if (!ReadParam(aReader, &length)) {
+ aReader->FatalError("JSStructuredCloneData length read failed");
+ return false;
+ }
+ MOZ_ASSERT(!(length % sizeof(uint64_t)));
+
+ // Borrowing is not suitable to use for IPC to hand out data because we often
+ // want to store the data somewhere for processing after IPC has released the
+ // underlying buffers.
+ //
+ // This deserializer previously used a mechanism to transfer ownership over
+ // the underlying buffers from IPC into the JSStructuredCloneData. This was
+ // removed when support for serializing over shared memory was added, as the
+ // benefit for avoiding copies was limited due to it only functioning for
+ // buffers under 64k in size (as larger buffers would be serialized using
+ // shared memory), and it added substantial complexity to the BufferList type
+ // and the IPC serialization layer due to things like buffer alignment. This
+ // can be revisited in the future if it turns out to be a noticable
+ // performance regression. (bug 1783242)
+
+ mozilla::BufferList<js::SystemAllocPolicy> buffers(0, 0, 4096);
+ MessageBufferReader bufReader(aReader, length);
+ uint32_t read = 0;
+ while (read < length) {
+ size_t bufLen;
+ char* buf = buffers.AllocateBytes(length - read, &bufLen);
+ if (!buf) {
+ // Would be nice to allow actor to control behaviour here (bug 1784307)
+ NS_ABORT_OOM(length - read);
+ return false;
+ }
+ if (!bufReader.ReadBytesInto(buf, bufLen)) {
+ aReader->FatalError("JSStructuredCloneData ReadBytesInto failed");
+ return false;
+ }
+ read += bufLen;
+ }
+
+ MOZ_ASSERT(read == length);
+ *aResult = JSStructuredCloneData(
+ std::move(buffers), JS::StructuredCloneScope::DifferentProcess,
+ OwnTransferablePolicy::IgnoreTransferablesIfAny);
+ return true;
+}
+
+} // namespace IPC