SerializedStructuredCloneBuffer.cpp (3123B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this file, 5 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "mozilla/ipc/SerializedStructuredCloneBuffer.h" 8 #include "js/StructuredClone.h" 9 10 namespace IPC { 11 12 void ParamTraits<JSStructuredCloneData>::Write(MessageWriter* aWriter, 13 const paramType& aParam) { 14 MOZ_ASSERT(!(aParam.Size() % sizeof(uint64_t))); 15 16 // We can only construct shared memory regions up to 4Gb in size, making that 17 // the maximum possible JSStructuredCloneData size. 18 mozilla::CheckedUint32 size = aParam.Size(); 19 if (!size.isValid()) { 20 aWriter->FatalError("JSStructuredCloneData over 4Gb in size"); 21 return; 22 } 23 WriteParam(aWriter, size.value()); 24 25 MessageBufferWriter bufWriter(aWriter, size.value()); 26 aParam.ForEachDataChunk([&](const char* aData, size_t aSize) { 27 return bufWriter.WriteBytes(aData, aSize); 28 }); 29 } 30 31 bool ParamTraits<JSStructuredCloneData>::Read(MessageReader* aReader, 32 paramType* aResult) { 33 uint32_t length = 0; 34 if (!ReadParam(aReader, &length)) { 35 aReader->FatalError("JSStructuredCloneData length read failed"); 36 return false; 37 } 38 MOZ_ASSERT(!(length % sizeof(uint64_t))); 39 40 // Borrowing is not suitable to use for IPC to hand out data because we often 41 // want to store the data somewhere for processing after IPC has released the 42 // underlying buffers. 43 // 44 // This deserializer previously used a mechanism to transfer ownership over 45 // the underlying buffers from IPC into the JSStructuredCloneData. This was 46 // removed when support for serializing over shared memory was added, as the 47 // benefit for avoiding copies was limited due to it only functioning for 48 // buffers under 64k in size (as larger buffers would be serialized using 49 // shared memory), and it added substantial complexity to the BufferList type 50 // and the IPC serialization layer due to things like buffer alignment. This 51 // can be revisited in the future if it turns out to be a noticable 52 // performance regression. (bug 1783242) 53 54 mozilla::BufferList<js::SystemAllocPolicy> buffers(0, 0, 4096); 55 MessageBufferReader bufReader(aReader, length); 56 uint32_t read = 0; 57 while (read < length) { 58 size_t bufLen; 59 char* buf = buffers.AllocateBytes(length - read, &bufLen); 60 if (!buf) { 61 // Would be nice to allow actor to control behaviour here (bug 1784307) 62 NS_ABORT_OOM(length - read); 63 return false; 64 } 65 if (!bufReader.ReadBytesInto(buf, bufLen)) { 66 aReader->FatalError("JSStructuredCloneData ReadBytesInto failed"); 67 return false; 68 } 69 read += bufLen; 70 } 71 72 MOZ_ASSERT(read == length); 73 *aResult = JSStructuredCloneData( 74 std::move(buffers), JS::StructuredCloneScope::DifferentProcess, 75 OwnTransferablePolicy::IgnoreTransferablesIfAny); 76 return true; 77 } 78 79 } // namespace IPC