// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "mojo/public/cpp/bindings/lib/native_struct_serialization.h"
#include "ipc/ipc_message_attachment.h"
#include "ipc/ipc_message_attachment_set.h"
#include "ipc/native_handle_type_converters.h"
#include "mojo/public/cpp/bindings/lib/serialization.h"
#include "mojo/public/cpp/bindings/lib/serialization_forward.h"
namespace mojo {
namespace internal {
// static
void UnmappedNativeStructSerializerImpl::Serialize(
const native::NativeStructPtr& input,
Buffer* buffer,
native::internal::NativeStruct_Data::BufferWriter* writer,
SerializationContext* context) {
if (!input)
return;
writer->Allocate(buffer);
Array_Data<uint8_t>::BufferWriter data_writer;
const mojo::internal::ContainerValidateParams data_validate_params(0, false,
nullptr);
mojo::internal::Serialize<ArrayDataView<uint8_t>>(
input->data, buffer, &data_writer, &data_validate_params, context);
writer->data()->data.Set(data_writer.data());
mojo::internal::Array_Data<mojo::internal::Pointer<
native::internal::SerializedHandle_Data>>::BufferWriter handles_writer;
const mojo::internal::ContainerValidateParams handles_validate_params(
0, false, nullptr);
mojo::internal::Serialize<
mojo::ArrayDataView<::mojo::native::SerializedHandleDataView>>(
input->handles, buffer, &handles_writer, &handles_validate_params,
context);
writer->data()->handles.Set(handles_writer.is_null() ? nullptr
: handles_writer.data());
}
// static
bool UnmappedNativeStructSerializerImpl::Deserialize(
native::internal::NativeStruct_Data* input,
native::NativeStructPtr* output,
SerializationContext* context) {
if (!input) {
output->reset();
return true;
}
native::NativeStructDataView data_view(input, context);
return StructTraits<::mojo::native::NativeStructDataView,
native::NativeStructPtr>::Read(data_view, output);
}
// static
void UnmappedNativeStructSerializerImpl::SerializeMessageContents(
IPC::Message* message,
Buffer* buffer,
native::internal::NativeStruct_Data::BufferWriter* writer,
SerializationContext* context) {
writer->Allocate(buffer);
// Allocate a uint8 array, initialize its header, and copy the Pickle in.
Array_Data<uint8_t>::BufferWriter data_writer;
data_writer.Allocate(message->payload_size(), buffer);
memcpy(data_writer->storage(), message->payload(), message->payload_size());
writer->data()->data.Set(data_writer.data());
if (message->attachment_set()->empty()) {
writer->data()->handles.Set(nullptr);
return;
}
mojo::internal::Array_Data<mojo::internal::Pointer<
native::internal::SerializedHandle_Data>>::BufferWriter handles_writer;
auto* attachments = message->attachment_set();
handles_writer.Allocate(attachments->size(), buffer);
for (unsigned i = 0; i < attachments->size(); ++i) {
native::internal::SerializedHandle_Data::BufferWriter handle_writer;
handle_writer.Allocate(buffer);
auto attachment = attachments->GetAttachmentAt(i);
ScopedHandle handle = attachment->TakeMojoHandle();
internal::Serializer<ScopedHandle, ScopedHandle>::Serialize(
handle, &handle_writer->the_handle, context);
handle_writer->type = static_cast<int32_t>(
mojo::ConvertTo<native::SerializedHandle::Type>(attachment->GetType()));
handles_writer.data()->at(i).Set(handle_writer.data());
}
writer->data()->handles.Set(handles_writer.data());
}
// static
bool UnmappedNativeStructSerializerImpl::DeserializeMessageAttachments(
native::internal::NativeStruct_Data* data,
SerializationContext* context,
IPC::Message* message) {
if (data->handles.is_null())
return true;
auto* handles_data = data->handles.Get();
for (size_t i = 0; i < handles_data->size(); ++i) {
auto* handle_data = handles_data->at(i).Get();
if (!handle_data)
return false;
ScopedHandle handle;
internal::Serializer<ScopedHandle, ScopedHandle>::Deserialize(
&handle_data->the_handle, &handle, context);
auto attachment = IPC::MessageAttachment::CreateFromMojoHandle(
std::move(handle),
mojo::ConvertTo<IPC::MessageAttachment::Type>(
static_cast<native::SerializedHandle::Type>(handle_data->type)));
message->attachment_set()->AddAttachment(std::move(attachment));
}
return true;
}
} // namespace internal
} // namespace mojo