Commit 454da004 authored by Marijn Kruisselbrink's avatar Marijn Kruisselbrink Committed by Commit Bot

Change how messages over a MessagePort are serialized.

In preparation for adding mojo Blob handles to the serialized message
port messages, this changes the logic in content::MessagePort to
serialize its messages using a mojom bindings generated struct. For now
the struct still just contains the blink encoded message and a list of
message port handles, but in the future blobs and other extra data can
be added much easier.

Bug: 351753, 740744
Change-Id: I411dd4398907eb7bbf21e630f5c82fb49798c440
Reviewed-on: https://chromium-review.googlesource.com/590082
Commit-Queue: Marijn Kruisselbrink <mek@chromium.org>
Reviewed-by: default avatarDarin Fisher <darin@chromium.org>
Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Reviewed-by: default avatarKen Rockot <rockot@chromium.org>
Cr-Commit-Position: refs/heads/master@{#490628}
parent 03fb959a
......@@ -607,6 +607,7 @@ mojom("mojo_bindings") {
"media/media_stream.mojom",
"media/renderer_audio_output_stream_factory.mojom",
"memory_coordinator.mojom",
"message_port.mojom",
"native_types.mojom",
"push_messaging.mojom",
"render_frame_message_filter.mojom",
......
......@@ -7,6 +7,7 @@
#include "base/bind.h"
#include "base/logging.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/common/message_port.mojom.h"
#include "mojo/public/cpp/system/message_pipe.h"
namespace content {
......@@ -49,61 +50,44 @@ void MessagePort::PostMessage(const base::string16& encoded_message,
uint32_t num_bytes = encoded_message.size() * sizeof(base::char16);
// NOTE: It is OK to ignore the return value of mojo::WriteMessageRaw here.
// NOTE: It is OK to ignore the return value of mojo::WriteMessageNew here.
// HTML MessagePorts have no way of reporting when the peer is gone.
if (ports.empty()) {
mojo::WriteMessageRaw(state_->handle().get(), encoded_message.data(),
num_bytes, nullptr, 0, MOJO_WRITE_MESSAGE_FLAG_NONE);
} else {
uint32_t num_handles = static_cast<uint32_t>(ports.size());
std::unique_ptr<MojoHandle[]> handles(new MojoHandle[num_handles]);
for (uint32_t i = 0; i < num_handles; ++i)
handles[i] = ports[i].ReleaseHandle().release().value();
mojo::WriteMessageRaw(state_->handle().get(), encoded_message.data(),
num_bytes, handles.get(), num_handles,
MOJO_WRITE_MESSAGE_FLAG_NONE);
}
mojom::MessagePortMessagePtr msg = mojom::MessagePortMessage::New();
msg->encoded_message.resize(num_bytes);
std::memcpy(msg->encoded_message.data(), encoded_message.data(), num_bytes);
msg->ports.resize(ports.size());
for (size_t i = 0; i < ports.size(); ++i)
msg->ports[i] = ports[i].ReleaseHandle();
mojo::Message mojo_message =
mojom::MessagePortMessage::SerializeAsMessage(&msg);
mojo::WriteMessageNew(state_->handle().get(), mojo_message.TakeMojoMessage(),
MOJO_WRITE_MESSAGE_FLAG_NONE);
}
bool MessagePort::GetMessage(base::string16* encoded_message,
std::vector<MessagePort>* ports) {
DCHECK(state_->handle().is_valid());
mojo::ScopedMessageHandle message;
MojoResult rv = mojo::ReadMessageNew(state_->handle().get(), &message,
mojo::ScopedMessageHandle message_handle;
MojoResult rv = mojo::ReadMessageNew(state_->handle().get(), &message_handle,
MOJO_READ_MESSAGE_FLAG_NONE);
if (rv != MOJO_RESULT_OK)
return false;
uint32_t num_bytes = 0;
uint32_t num_handles = 0;
void* buffer;
std::vector<mojo::ScopedHandle> handles;
rv = MojoGetSerializedMessageContents(
message->value(), &buffer, &num_bytes, nullptr, &num_handles,
MOJO_GET_SERIALIZED_MESSAGE_CONTENTS_FLAG_NONE);
if (rv == MOJO_RESULT_RESOURCE_EXHAUSTED) {
handles.resize(num_handles);
rv = MojoGetSerializedMessageContents(
message->value(), &buffer, &num_bytes,
reinterpret_cast<MojoHandle*>(handles.data()), &num_handles,
MOJO_GET_SERIALIZED_MESSAGE_CONTENTS_FLAG_NONE);
}
if (rv != MOJO_RESULT_OK)
mojo::Message message(std::move(message_handle));
mojom::MessagePortMessagePtr msg;
bool success = mojom::MessagePortMessage::DeserializeFromMessage(
std::move(message), &msg);
if (!success || !msg)
return false;
DCHECK_EQ(0u, num_bytes % sizeof(base::char16));
encoded_message->resize(num_bytes / sizeof(base::char16));
if (num_bytes)
memcpy(&encoded_message->at(0), buffer, num_bytes);
if (!handles.empty()) {
ports->resize(handles.size());
for (uint32_t i = 0; i < num_handles; ++i) {
ports->at(i) = MessagePort(
mojo::ScopedMessagePipeHandle::From(std::move(handles[i])));
}
}
DCHECK_EQ(0u, msg->encoded_message.size() % sizeof(base::char16));
encoded_message->resize(msg->encoded_message.size() / sizeof(base::char16));
std::memcpy(&encoded_message->at(0), msg->encoded_message.data(),
msg->encoded_message.size());
ports->resize(msg->ports.size());
for (size_t i = 0; i < ports->size(); ++i)
ports->at(i) = MessagePort(std::move(msg->ports[i]));
return true;
}
......
// Copyright 2017 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.
module content.mojom;
// This struct represents a message as it is sent across a MessagePort. A
// MessagePort itself is represented as a raw mojo message pipe, and messages
// on it are (in both directions) serialized versions of this struct.
struct MessagePortMessage {
// The actual message data, as encoded by blink::SerializedScriptValue.
array<uint8> encoded_message;
// Any ports being transfered as part of this message.
array<handle<message_pipe>> ports;
};
......@@ -53,6 +53,7 @@ DataArrayType StructSerializeImpl(UserType* input) {
template <typename MojomType, typename UserType>
bool StructDeserializeImpl(const void* data,
size_t data_num_bytes,
std::vector<mojo::ScopedHandle> handles,
UserType* output,
bool (*validate_func)(const void*,
ValidationContext*)) {
......@@ -76,10 +77,11 @@ bool StructDeserializeImpl(const void* data,
DCHECK(base::IsValueInRangeForNumericType<uint32_t>(data_num_bytes));
ValidationContext validation_context(
input_buffer, static_cast<uint32_t>(data_num_bytes), 0, 0);
input_buffer, static_cast<uint32_t>(data_num_bytes), handles.size(), 0);
bool result = false;
if (validate_func(input_buffer, &validation_context)) {
SerializationContext context;
*context.mutable_handles() = std::move(handles);
result = Deserialize<MojomType>(
reinterpret_cast<DataType*>(const_cast<void*>(input_buffer)), output,
&context);
......
......@@ -79,7 +79,7 @@ class {{export_attribute}} {{struct.name}} {
size_t data_num_bytes,
UserType* output) {
return mojo::internal::StructDeserializeImpl<{{struct.name}}::DataView>(
data, data_num_bytes, output, Validate);
data, data_num_bytes, std::vector<mojo::ScopedHandle>(), output, Validate);
}
template <typename UserType>
......@@ -89,6 +89,14 @@ class {{export_attribute}} {{struct.name}} {
input.size() == 0 ? nullptr : &input.front(), input.size(), output);
}
template <typename UserType>
static bool DeserializeFromMessage(mojo::Message input,
UserType* output) {
return mojo::internal::StructDeserializeImpl<{{struct.name}}::DataView>(
input.payload(), input.payload_num_bytes(),
std::move(*input.mutable_handles()), output, Validate);
}
{#--- Struct members #}
{% for field in struct.fields %}
{%- set type = field.kind|cpp_wrapper_type %}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment