Commit 7933caa6 authored by Kevin Marshall's avatar Kevin Marshall Committed by Commit Bot

[Fuchsia] Add support for remote MessagePorts & promote to shared source_set.

Refactors the FIDL/MessagePort adapter classes and adds support for
adapting InterfaceHandle<MessagePort> to Mojo MessagePipes.

Bug: 953958
Change-Id: I9c208cf21bc0956c8f3856e23dbd4302e981abd0
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1612351
Commit-Queue: Kevin Marshall <kmarshall@chromium.org>
Reviewed-by: default avatarWez <wez@chromium.org>
Reviewed-by: default avatarMarijn Kruisselbrink <mek@chromium.org>
Reviewed-by: default avatarKen Rockot <rockot@google.com>
Cr-Commit-Position: refs/heads/master@{#660647}
parent d01aed9d
...@@ -40,6 +40,23 @@ source_set("modular") { ...@@ -40,6 +40,23 @@ source_set("modular") {
] ]
} }
# FIDL/Mojo adapters for MessagePorts.
source_set("message_port") {
sources = [
"message_port.cc",
]
public = [
"message_port.h",
]
deps = [
":base",
"//base",
"//mojo/public/cpp/bindings",
"//third_party/blink/public/common",
"//third_party/fuchsia-sdk/sdk:web",
]
}
source_set("test_support") { source_set("test_support") {
testonly = true testonly = true
sources = [ sources = [
......
include_rules = [
"+mojo/public",
"+third_party/blink/public/common/messaging",
"+third_party/blink/public/mojom/messaging",
]
This diff is collapsed.
// Copyright 2018 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.
#ifndef FUCHSIA_BASE_MESSAGE_PORT_H_
#define FUCHSIA_BASE_MESSAGE_PORT_H_
#include <fuchsia/web/cpp/fidl.h>
#include <lib/fidl/cpp/binding.h>
#include <memory>
#include "base/containers/circular_deque.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "mojo/public/cpp/bindings/connector.h"
#include "mojo/public/cpp/bindings/message.h"
#include "mojo/public/cpp/system/message_pipe.h"
namespace cr_fuchsia {
// Creates a connected MessagePort from a FIDL MessagePort request and
// returns a handle to its peer Mojo pipe.
mojo::ScopedMessagePipeHandle MessagePortFromFidl(
fidl::InterfaceRequest<fuchsia::web::MessagePort> fidl_port);
// Creates a connected MessagePort from a remote FIDL MessagePort handle,
// returns a handle to its peer Mojo pipe.
mojo::ScopedMessagePipeHandle MessagePortFromFidl(
fidl::InterfaceHandle<fuchsia::web::MessagePort> fidl_port);
// Creates a connected MessagePort from a transferred Mojo MessagePort and
// returns a handle to its FIDL interface peer.
fidl::InterfaceHandle<fuchsia::web::MessagePort> MessagePortFromMojo(
mojo::ScopedMessagePipeHandle mojo_port);
} // namespace cr_fuchsia
#endif // FUCHSIA_BASE_MESSAGE_PORT_H_
...@@ -72,6 +72,7 @@ component("web_engine_core") { ...@@ -72,6 +72,7 @@ component("web_engine_core") {
"//content/public/common", "//content/public/common",
"//content/public/renderer", "//content/public/renderer",
"//fuchsia/base", "//fuchsia/base",
"//fuchsia/base:message_port",
"//fuchsia/base:modular", "//fuchsia/base:modular",
"//mojo/public/cpp/bindings", "//mojo/public/cpp/bindings",
"//services/network/public/cpp", "//services/network/public/cpp",
...@@ -104,8 +105,6 @@ component("web_engine_core") { ...@@ -104,8 +105,6 @@ component("web_engine_core") {
"browser/discarding_event_filter.h", "browser/discarding_event_filter.h",
"browser/frame_impl.cc", "browser/frame_impl.cc",
"browser/frame_impl.h", "browser/frame_impl.h",
"browser/message_port_impl.cc",
"browser/message_port_impl.h",
"browser/web_engine_browser_context.cc", "browser/web_engine_browser_context.cc",
"browser/web_engine_browser_context.h", "browser/web_engine_browser_context.h",
"browser/web_engine_browser_main.cc", "browser/web_engine_browser_main.cc",
......
...@@ -19,8 +19,8 @@ ...@@ -19,8 +19,8 @@
#include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents.h"
#include "content/public/common/was_activated_option.h" #include "content/public/common/was_activated_option.h"
#include "fuchsia/base/mem_buffer_util.h" #include "fuchsia/base/mem_buffer_util.h"
#include "fuchsia/base/message_port.h"
#include "fuchsia/engine/browser/context_impl.h" #include "fuchsia/engine/browser/context_impl.h"
#include "fuchsia/engine/browser/message_port_impl.h"
#include "mojo/public/cpp/system/platform_handle.h" #include "mojo/public/cpp/system/platform_handle.h"
#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h" #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
#include "third_party/blink/public/common/logging/logging_utils.h" #include "third_party/blink/public/common/logging/logging_utils.h"
...@@ -393,7 +393,7 @@ void FrameImpl::PostMessage(std::string origin, ...@@ -393,7 +393,7 @@ void FrameImpl::PostMessage(std::string origin,
for (fuchsia::web::OutgoingTransferable& outgoing : for (fuchsia::web::OutgoingTransferable& outgoing :
*message.mutable_outgoing_transfer()) { *message.mutable_outgoing_transfer()) {
mojo::ScopedMessagePipeHandle port = mojo::ScopedMessagePipeHandle port =
MessagePortImpl::FromFidl(std::move(outgoing.message_port())); cr_fuchsia::MessagePortFromFidl(std::move(outgoing.message_port()));
if (!port) { if (!port) {
result.set_err(fuchsia::web::FrameError::INTERNAL_ERROR); result.set_err(fuchsia::web::FrameError::INTERNAL_ERROR);
callback(std::move(result)); callback(std::move(result));
......
// Copyright 2018 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 "fuchsia/engine/browser/message_port_impl.h"
#include <stdint.h>
#include <lib/fit/function.h>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "base/bind.h"
#include "base/fuchsia/fuchsia_logging.h"
#include "base/macros.h"
#include "fuchsia/base/mem_buffer_util.h"
#include "mojo/public/cpp/system/message_pipe.h"
#include "third_party/blink/public/common/messaging/message_port_channel.h"
#include "third_party/blink/public/common/messaging/string_message_codec.h"
#include "third_party/blink/public/common/messaging/transferable_message_struct_traits.h"
#include "third_party/blink/public/mojom/messaging/transferable_message.mojom.h"
namespace {
// Converts a message posted to a JS MessagePort to a WebMessage.
// Returns an unset Optional<> if the message could not be converted.
base::Optional<fuchsia::web::WebMessage> FromMojoMessage(
mojo::Message message) {
fuchsia::web::WebMessage converted;
blink::TransferableMessage transferable_message;
if (!blink::mojom::TransferableMessage::DeserializeFromMessage(
std::move(message), &transferable_message))
return {};
if (!transferable_message.ports.empty()) {
std::vector<fuchsia::web::IncomingTransferable> transferables;
for (const blink::MessagePortChannel& port : transferable_message.ports) {
fuchsia::web::IncomingTransferable incoming;
incoming.set_message_port(
MessagePortImpl::FromMojo(port.ReleaseHandle()));
transferables.emplace_back(std::move(incoming));
}
converted.set_incoming_transfer(std::move(transferables));
}
base::string16 data_utf16;
if (!blink::DecodeStringMessage(transferable_message.encoded_message,
&data_utf16)) {
return {};
}
std::string data_utf8;
if (!base::UTF16ToUTF8(data_utf16.data(), data_utf16.size(), &data_utf8))
return {};
base::STLClearObject(&data_utf16);
fuchsia::mem::Buffer data = cr_fuchsia::MemBufferFromString(data_utf8);
if (!data.vmo) {
return {};
}
converted.set_data(std::move(data));
return converted;
}
} // namespace
MessagePortImpl::MessagePortImpl(mojo::ScopedMessagePipeHandle mojo_port)
: binding_(this) {
connector_ = std::make_unique<mojo::Connector>(
std::move(mojo_port), mojo::Connector::SINGLE_THREADED_SEND,
base::ThreadTaskRunnerHandle::Get());
connector_->set_incoming_receiver(this);
connector_->set_connection_error_handler(
base::BindOnce(&MessagePortImpl::OnDisconnected, base::Unretained(this)));
binding_.set_error_handler([this](zx_status_t status) {
ZX_LOG_IF(ERROR, status != ZX_ERR_PEER_CLOSED, status)
<< " MessagePort disconnected.";
OnDisconnected();
});
}
MessagePortImpl::~MessagePortImpl() = default;
void MessagePortImpl::OnDisconnected() {
// |connector_| and |binding_| are implicitly unbound.
delete this;
}
void MessagePortImpl::PostMessage(fuchsia::web::WebMessage message,
PostMessageCallback callback) {
fuchsia::web::MessagePort_PostMessage_Result result;
if (!message.has_data()) {
result.set_err(fuchsia::web::FrameError::NO_DATA_IN_MESSAGE);
callback(std::move(result));
return;
}
base::string16 data_utf16;
if (!cr_fuchsia::ReadUTF8FromVMOAsUTF16(message.data(), &data_utf16)) {
result.set_err(fuchsia::web::FrameError::BUFFER_NOT_UTF8);
callback(std::move(result));
return;
}
blink::TransferableMessage transfer_message;
if (message.has_outgoing_transfer()) {
for (fuchsia::web::OutgoingTransferable& outgoing :
*message.mutable_outgoing_transfer()) {
transfer_message.ports.emplace_back(
MessagePortImpl::FromFidl(std::move(outgoing.message_port())));
}
}
transfer_message.owned_encoded_message =
blink::EncodeStringMessage(data_utf16);
transfer_message.encoded_message = transfer_message.owned_encoded_message;
mojo::Message mojo_message =
blink::mojom::TransferableMessage::SerializeAsMessage(&transfer_message);
CHECK(connector_->Accept(&mojo_message));
result.set_response(fuchsia::web::MessagePort_PostMessage_Response());
callback(std::move(result));
}
void MessagePortImpl::ReceiveMessage(
fuchsia::web::MessagePort::ReceiveMessageCallback callback) {
pending_client_read_cb_ = std::move(callback);
MaybeDeliverToClient();
}
void MessagePortImpl::MaybeDeliverToClient() {
// Do nothing if the client hasn't requested a read, or if there's nothing
// to read.
if (!pending_client_read_cb_ || message_queue_.empty()) {
return;
}
auto pending_client_read_cb = std::exchange(pending_client_read_cb_, nullptr);
pending_client_read_cb(std::move(message_queue_.front()));
message_queue_.pop_front();
}
bool MessagePortImpl::Accept(mojo::Message* message) {
base::Optional<fuchsia::web::WebMessage> message_converted =
FromMojoMessage(std::move(*message));
if (!message_converted) {
DLOG(ERROR) << "Couldn't decode MessageChannel from Mojo pipe.";
return false;
}
message_queue_.emplace_back(std::move(message_converted.value()));
MaybeDeliverToClient();
return true;
}
// static
mojo::ScopedMessagePipeHandle MessagePortImpl::FromFidl(
fidl::InterfaceRequest<fuchsia::web::MessagePort> port) {
mojo::ScopedMessagePipeHandle client_port;
mojo::ScopedMessagePipeHandle content_port;
mojo::CreateMessagePipe(0, &content_port, &client_port);
MessagePortImpl* port_impl = new MessagePortImpl(std::move(client_port));
port_impl->binding_.Bind(std::move(port));
return content_port;
}
// static
fidl::InterfaceHandle<fuchsia::web::MessagePort> MessagePortImpl::FromMojo(
mojo::ScopedMessagePipeHandle port) {
MessagePortImpl* created_port = new MessagePortImpl(std::move(port));
return created_port->binding_.NewBinding();
}
// Copyright 2018 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.
#ifndef FUCHSIA_ENGINE_BROWSER_MESSAGE_PORT_IMPL_H_
#define FUCHSIA_ENGINE_BROWSER_MESSAGE_PORT_IMPL_H_
#include <fuchsia/web/cpp/fidl.h>
#include <lib/fidl/cpp/binding.h>
#include <memory>
#include "base/containers/circular_deque.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "mojo/public/cpp/bindings/connector.h"
#include "mojo/public/cpp/bindings/message.h"
#include "mojo/public/cpp/system/message_pipe.h"
// Defines the implementation of a MessagePort which routes messages from
// FIDL clients to web content, or vice versa. Every MessagePortImpl has a FIDL
// port and a Mojo port.
//
// MessagePortImpl instances are self-managed; they destroy themselves when
// the connection is terminated from either the Mojo or FIDL side.
class MessagePortImpl : public fuchsia::web::MessagePort,
public mojo::MessageReceiver {
public:
// Creates a connected MessagePort from a FIDL MessagePort request and
// returns a handle to its peer Mojo pipe.
static mojo::ScopedMessagePipeHandle FromFidl(
fidl::InterfaceRequest<fuchsia::web::MessagePort> port);
// Creates a connected MessagePort from a transferred Mojo MessagePort and
// returns a handle to its FIDL interface peer.
static fidl::InterfaceHandle<fuchsia::web::MessagePort> FromMojo(
mojo::ScopedMessagePipeHandle port);
private:
explicit MessagePortImpl(mojo::ScopedMessagePipeHandle mojo_port);
// Non-public to ensure that only this object may destroy itself.
~MessagePortImpl() override;
// fuchsia::web::MessagePort implementation.
void PostMessage(fuchsia::web::WebMessage message,
PostMessageCallback callback) override;
void ReceiveMessage(ReceiveMessageCallback callback) override;
// Called when the connection to Blink or FIDL is terminated.
void OnDisconnected();
// Sends the next message enqueued in |message_queue_| to the client,
// if the client has requested a message.
void MaybeDeliverToClient();
// mojo::MessageReceiver implementation.
bool Accept(mojo::Message* message) override;
fidl::Binding<fuchsia::web::MessagePort> binding_;
base::circular_deque<fuchsia::web::WebMessage> message_queue_;
ReceiveMessageCallback pending_client_read_cb_;
std::unique_ptr<mojo::Connector> connector_;
DISALLOW_COPY_AND_ASSIGN(MessagePortImpl);
};
#endif // FUCHSIA_ENGINE_BROWSER_MESSAGE_PORT_IMPL_H_
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