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") { ...@@ -607,6 +607,7 @@ mojom("mojo_bindings") {
"media/media_stream.mojom", "media/media_stream.mojom",
"media/renderer_audio_output_stream_factory.mojom", "media/renderer_audio_output_stream_factory.mojom",
"memory_coordinator.mojom", "memory_coordinator.mojom",
"message_port.mojom",
"native_types.mojom", "native_types.mojom",
"push_messaging.mojom", "push_messaging.mojom",
"render_frame_message_filter.mojom", "render_frame_message_filter.mojom",
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "base/bind.h" #include "base/bind.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/threading/thread_task_runner_handle.h" #include "base/threading/thread_task_runner_handle.h"
#include "content/common/message_port.mojom.h"
#include "mojo/public/cpp/system/message_pipe.h" #include "mojo/public/cpp/system/message_pipe.h"
namespace content { namespace content {
...@@ -49,61 +50,44 @@ void MessagePort::PostMessage(const base::string16& encoded_message, ...@@ -49,61 +50,44 @@ void MessagePort::PostMessage(const base::string16& encoded_message,
uint32_t num_bytes = encoded_message.size() * sizeof(base::char16); 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. // HTML MessagePorts have no way of reporting when the peer is gone.
if (ports.empty()) { mojom::MessagePortMessagePtr msg = mojom::MessagePortMessage::New();
mojo::WriteMessageRaw(state_->handle().get(), encoded_message.data(), msg->encoded_message.resize(num_bytes);
num_bytes, nullptr, 0, MOJO_WRITE_MESSAGE_FLAG_NONE); std::memcpy(msg->encoded_message.data(), encoded_message.data(), num_bytes);
} else { msg->ports.resize(ports.size());
uint32_t num_handles = static_cast<uint32_t>(ports.size()); for (size_t i = 0; i < ports.size(); ++i)
std::unique_ptr<MojoHandle[]> handles(new MojoHandle[num_handles]); msg->ports[i] = ports[i].ReleaseHandle();
for (uint32_t i = 0; i < num_handles; ++i) mojo::Message mojo_message =
handles[i] = ports[i].ReleaseHandle().release().value(); mojom::MessagePortMessage::SerializeAsMessage(&msg);
mojo::WriteMessageRaw(state_->handle().get(), encoded_message.data(), mojo::WriteMessageNew(state_->handle().get(), mojo_message.TakeMojoMessage(),
num_bytes, handles.get(), num_handles, MOJO_WRITE_MESSAGE_FLAG_NONE);
MOJO_WRITE_MESSAGE_FLAG_NONE);
}
} }
bool MessagePort::GetMessage(base::string16* encoded_message, bool MessagePort::GetMessage(base::string16* encoded_message,
std::vector<MessagePort>* ports) { std::vector<MessagePort>* ports) {
DCHECK(state_->handle().is_valid()); DCHECK(state_->handle().is_valid());
mojo::ScopedMessageHandle message; mojo::ScopedMessageHandle message_handle;
MojoResult rv = mojo::ReadMessageNew(state_->handle().get(), &message, MojoResult rv = mojo::ReadMessageNew(state_->handle().get(), &message_handle,
MOJO_READ_MESSAGE_FLAG_NONE); MOJO_READ_MESSAGE_FLAG_NONE);
if (rv != MOJO_RESULT_OK) if (rv != MOJO_RESULT_OK)
return false; return false;
uint32_t num_bytes = 0; mojo::Message message(std::move(message_handle));
uint32_t num_handles = 0; mojom::MessagePortMessagePtr msg;
void* buffer; bool success = mojom::MessagePortMessage::DeserializeFromMessage(
std::vector<mojo::ScopedHandle> handles; std::move(message), &msg);
rv = MojoGetSerializedMessageContents( if (!success || !msg)
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)
return false; return false;
DCHECK_EQ(0u, num_bytes % sizeof(base::char16)); DCHECK_EQ(0u, msg->encoded_message.size() % sizeof(base::char16));
encoded_message->resize(num_bytes / sizeof(base::char16)); encoded_message->resize(msg->encoded_message.size() / sizeof(base::char16));
if (num_bytes) std::memcpy(&encoded_message->at(0), msg->encoded_message.data(),
memcpy(&encoded_message->at(0), buffer, num_bytes); msg->encoded_message.size());
ports->resize(msg->ports.size());
if (!handles.empty()) { for (size_t i = 0; i < ports->size(); ++i)
ports->resize(handles.size()); ports->at(i) = MessagePort(std::move(msg->ports[i]));
for (uint32_t i = 0; i < num_handles; ++i) {
ports->at(i) = MessagePort(
mojo::ScopedMessagePipeHandle::From(std::move(handles[i])));
}
}
return true; 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) { ...@@ -53,6 +53,7 @@ DataArrayType StructSerializeImpl(UserType* input) {
template <typename MojomType, typename UserType> template <typename MojomType, typename UserType>
bool StructDeserializeImpl(const void* data, bool StructDeserializeImpl(const void* data,
size_t data_num_bytes, size_t data_num_bytes,
std::vector<mojo::ScopedHandle> handles,
UserType* output, UserType* output,
bool (*validate_func)(const void*, bool (*validate_func)(const void*,
ValidationContext*)) { ValidationContext*)) {
...@@ -76,10 +77,11 @@ bool StructDeserializeImpl(const void* data, ...@@ -76,10 +77,11 @@ bool StructDeserializeImpl(const void* data,
DCHECK(base::IsValueInRangeForNumericType<uint32_t>(data_num_bytes)); DCHECK(base::IsValueInRangeForNumericType<uint32_t>(data_num_bytes));
ValidationContext validation_context( 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; bool result = false;
if (validate_func(input_buffer, &validation_context)) { if (validate_func(input_buffer, &validation_context)) {
SerializationContext context; SerializationContext context;
*context.mutable_handles() = std::move(handles);
result = Deserialize<MojomType>( result = Deserialize<MojomType>(
reinterpret_cast<DataType*>(const_cast<void*>(input_buffer)), output, reinterpret_cast<DataType*>(const_cast<void*>(input_buffer)), output,
&context); &context);
......
...@@ -79,7 +79,7 @@ class {{export_attribute}} {{struct.name}} { ...@@ -79,7 +79,7 @@ class {{export_attribute}} {{struct.name}} {
size_t data_num_bytes, size_t data_num_bytes,
UserType* output) { UserType* output) {
return mojo::internal::StructDeserializeImpl<{{struct.name}}::DataView>( 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> template <typename UserType>
...@@ -89,6 +89,14 @@ class {{export_attribute}} {{struct.name}} { ...@@ -89,6 +89,14 @@ class {{export_attribute}} {{struct.name}} {
input.size() == 0 ? nullptr : &input.front(), input.size(), output); 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 #} {#--- Struct members #}
{% for field in struct.fields %} {% for field in struct.fields %}
{%- set type = field.kind|cpp_wrapper_type %} {%- 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