Commit ac18495f authored by Kevin Marshall's avatar Kevin Marshall Committed by Commit Bot

[cast_runner] Use abstracted MessagePort for MessageChannel I/O.

Replaces uses of Blink MessagePort/MessageChannel with
cast_api_bindings::MessagePort.

Updates Fuchsia and Cast tests to use the new
cast_api_bindings::MessagePort API.

Removes Mojo and Blink deps.

Bug: 1131102,1126571
Change-Id: Ib4f2da74d03dcbae9f271f5a2f7c069d8e9f0e3d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2458877
Commit-Queue: Kevin Marshall <kmarshall@chromium.org>
Reviewed-by: default avatarYuchen Liu <yucliu@chromium.org>
Reviewed-by: default avatarFabrice de Gans-Riberi <fdegans@chromium.org>
Cr-Commit-Position: refs/heads/master@{#815831}
parent 7253c6cc
......@@ -65,9 +65,9 @@ if (is_linux || is_chromeos || is_android) {
"//base",
"//chromecast/browser:public",
"//components/cast/api_bindings:manager",
"//components/cast/message_port",
"//components/cast/named_message_port_connector",
"//components/on_load_script_injector/browser",
"//third_party/blink/public/common",
]
}
......@@ -87,6 +87,7 @@ if (is_linux || is_chromeos || is_android) {
"//chromecast/bindings:bindings_manager_cast",
"//chromecast/browser:browser",
"//chromecast/browser:public",
"//components/cast/message_port:test_message_port_receiver",
"//components/cast/named_message_port_connector:resources",
"//content/public/browser",
"//content/test:test_support",
......
......@@ -9,7 +9,5 @@ include_rules = [
"+fuchsia",
"+mojo/public",
"+net/test",
"+third_party/blink/public/common/messaging",
"+third_party/blink/public/mojom/messaging",
"+ui/base/resource",
]
derekjchow@chromium.org
lijiawei@chromium.org
maclellant@chromium.org
kmarshall@chromium.org
......@@ -25,13 +25,8 @@ BindingsManagerCast::BindingsManagerCast(
port_connector_ =
std::make_unique<NamedMessagePortConnectorCast>(cast_web_contents_, this);
// TODO(crbug.com/1135379): Remove static_cast with deprecated OnPortConnected
// overload
port_connector_->RegisterPortHandler(
base::BindRepeating(static_cast<bool (BindingsManagerCast::*)(
base::StringPiece, blink::WebMessagePort)>(
&BindingsManagerCast::OnPortConnected),
base::Unretained(this)));
port_connector_->RegisterPortHandler(base::BindRepeating(
&BindingsManagerCast::OnPortConnected, base::Unretained(this)));
}
BindingsManagerCast::~BindingsManagerCast() = default;
......
......@@ -23,6 +23,7 @@
#include "chromecast/browser/cast_browser_context.h"
#include "chromecast/browser/cast_browser_process.h"
#include "chromecast/browser/cast_web_contents_impl.h"
#include "components/cast/message_port/test_message_port_receiver.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_base.h"
......@@ -62,15 +63,6 @@ base::FilePath GetTestDataFilePath(const std::string& name) {
return file_path.Append(GetTestDataPath()).AppendASCII(name);
}
base::Optional<std::string> ReadMessagePayloadAsUtf8(
blink::WebMessagePort::Message message) {
std::string output;
if (!base::UTF16ToUTF8(message.data.data(), message.data.size(), &output))
return base::nullopt;
return base::make_optional<std::string>(output);
}
class TitleChangeObserver : public CastWebContents::Observer {
public:
TitleChangeObserver() = default;
......@@ -109,119 +101,6 @@ class TitleChangeObserver : public CastWebContents::Observer {
DISALLOW_COPY_AND_ASSIGN(TitleChangeObserver);
};
// Test class for communicating with connector.html.
class TestBindingBackend : public blink::WebMessagePort::MessageReceiver {
public:
TestBindingBackend(bindings::BindingsManagerCast* bindings_manager)
: bindings_manager_(bindings_manager) {
constexpr char kPortName[] = "hello";
bindings_manager_->RegisterPortHandler(
kPortName, base::BindRepeating(&TestBindingBackend::OnPortConnected,
base::Unretained(this)));
}
~TestBindingBackend() override {
port_.Reset();
constexpr char kPortName[] = "hello";
bindings_manager_->UnregisterPortHandler(kPortName);
}
// Start the RunLoop until OnPortConnected.
void RunUntilPortConnected() {
if (port_.IsValid())
return;
base::RunLoop run_loop;
quit_closure_ = run_loop.QuitClosure();
run_loop.Run();
}
// Run the callback if there is at least one available message
// cached.
void ReceiveMessage(base::OnceCallback<void(std::string)> callback) {
ASSERT_TRUE(message_received_callback_.is_null())
<< "Only one waiting event is allowed.";
// Run the callback immediately if we have cached some messages.
if (!message_queue_.empty()) {
std::move(message_received_callback_).Run(message_queue_.front());
message_queue_.pop_front();
return;
}
message_received_callback_ = std::move(callback);
}
void SendMessageToPage(base::StringPiece message) {
if (!port_.IsValid())
return;
DCHECK(!message.empty());
blink::WebMessagePort::Message blink_message(base::UTF8ToUTF16(message));
port_.PostMessage(std::move(blink_message));
}
void SetPortDisconnectedCallback(
base::OnceClosure port_disconnected_callback) {
DCHECK(!port_disconnected_callback_);
port_disconnected_callback_ = std::move(port_disconnected_callback);
}
private:
// Called when a port was received from the page.
void OnPortConnected(blink::WebMessagePort port) {
if (!quit_closure_.is_null()) {
std::move(quit_closure_).Run();
}
port_ = std::move(port);
port_.SetReceiver(this, base::ThreadTaskRunnerHandle::Get());
}
// blink::WebMessagePort::MessageReceiver implementation:
bool OnMessage(blink::WebMessagePort::Message message) override {
base::Optional<std::string> message_json =
ReadMessagePayloadAsUtf8(std::move(message));
if (!message_json)
return false;
if (message_received_callback_) {
// Number of cached messages must be zero in this case.
DCHECK(message_queue_.empty());
std::move(message_received_callback_).Run(message_json.value());
return true;
}
// Cache received message until external caller access it
// via TestBindingBackend::ReceiveMessage
message_queue_.emplace_back(message_json.value());
return true;
}
// blink::WebMessagePort::MessageReceiver implementation:
// Called when the peer disconnected the port.
void OnPipeError() override {
LOG(INFO) << "TestBindingBackend port disconnected.";
port_.Reset();
if (port_disconnected_callback_) {
std::move(port_disconnected_callback_).Run();
}
}
base::OnceClosure quit_closure_;
bindings::BindingsManager* const bindings_manager_;
// Used for sending and receiving messages over the MessagePort.
blink::WebMessagePort port_;
base::circular_deque<std::string> message_queue_;
base::OnceCallback<void(std::string)> message_received_callback_;
base::OnceClosure port_disconnected_callback_;
DISALLOW_COPY_AND_ASSIGN(TestBindingBackend);
};
// =============================================================================
// Mocks
// =============================================================================
......@@ -316,6 +195,38 @@ class BindingsManagerCastBrowserTest : public content::BrowserTestBase {
DISALLOW_COPY_AND_ASSIGN(BindingsManagerCastBrowserTest);
};
// Handles connected ports from the NamedMessagePortConnector and
// provides a convenience methods for waiting for and then returning the port
// synchronously.
class MessagePortConnectionHandler {
public:
MessagePortConnectionHandler() {}
~MessagePortConnectionHandler() {}
cast_api_bindings::Manager::MessagePortConnectedHandler GetConnectCallback() {
return base::BindRepeating(&MessagePortConnectionHandler::OnConnect,
base::Unretained(this));
}
std::unique_ptr<cast_api_bindings::MessagePort> RunUntilPortConnected() {
base::RunLoop run_loop;
on_port_connected_ = run_loop.QuitClosure();
run_loop.Run();
return std::move(port_);
}
private:
void OnConnect(std::unique_ptr<cast_api_bindings::MessagePort> port) {
DCHECK(on_port_connected_);
port_ = std::move(port);
std::move(on_port_connected_).Run();
}
base::OnceClosure on_port_connected_;
std::unique_ptr<cast_api_bindings::MessagePort> port_;
};
// =============================================================================
// Test cases
// =============================================================================
......@@ -340,57 +251,32 @@ IN_PROC_BROWSER_TEST_F(BindingsManagerCastBrowserTest, EndToEnd) {
GURL test_url =
content::GetFileUrlWithQuery(GetTestDataFilePath("connector.html"), "");
// Register test port handler.
auto test_binding_backend =
std::make_unique<TestBindingBackend>(bindings_manager_.get());
// TestBindingBackend test_binding_backend(bindings_manager_.get());
MessagePortConnectionHandler connect_handler;
bindings_manager_->RegisterPortHandler("hello",
connect_handler.GetConnectCallback());
// Load test page.
constexpr char kTestPageTitle[] = "bindings";
cast_web_contents_->LoadUrl(test_url);
title_change_observer_.RunUntilTitleEquals(kTestPageTitle);
// Start RunLoop until TestBindingBackend receives MessagePort.
test_binding_backend->RunUntilPortConnected();
auto message_port = connect_handler.RunUntilPortConnected();
cast_api_bindings::TestMessagePortReceiver receiver;
message_port->SetReceiver(&receiver);
// Send ping message to the test page.
test_binding_backend->SendMessageToPage("ping");
message_port->PostMessage("ping");
// Test that message are received in order.
std::vector<std::string> test_messages = {"early 1", "early 2", "ack ping"};
for (auto test_message : test_messages) {
base::RunLoop run_loop;
auto quit_closure = run_loop.QuitClosure();
auto received_message_callback = base::BindOnce(
[](base::OnceClosure loop_quit_closure, std::string expected_msg,
std::string port_msg) {
EXPECT_EQ(expected_msg, port_msg);
std::move(loop_quit_closure).Run();
},
std::move(quit_closure), test_message);
test_binding_backend->ReceiveMessage(std::move(received_message_callback));
run_loop.Run();
}
receiver.RunUntilMessageCountEqual(3);
EXPECT_EQ(receiver.buffer()[0].first, "early 1");
EXPECT_EQ(receiver.buffer()[1].first, "early 2");
EXPECT_EQ(receiver.buffer()[2].first, "ack ping");
// Ensure that the MessagePort is dropped when navigating away.
{
base::RunLoop run_loop;
auto port_disconnected_callback = base::BindOnce(
[](base::OnceClosure loop_quit_closure) {
std::move(loop_quit_closure).Run();
},
run_loop.QuitClosure());
test_binding_backend->SetPortDisconnectedCallback(
std::move(port_disconnected_callback));
cast_web_contents_->LoadUrl(GURL(url::kAboutBlankURL));
run_loop.Run();
}
cast_web_contents_->LoadUrl(GURL(url::kAboutBlankURL));
receiver.RunUntilDisconnected();
// Destruct the binding backend to unregister itself from BindingsManagerCast
test_binding_backend.reset();
bindings_manager_->UnregisterPortHandler("hello");
}
} // namespace chromecast
......
......@@ -11,6 +11,7 @@
#include "base/strings/utf_string_conversions.h"
#include "chromecast/browser/cast_web_contents.h"
#include "components/cast/api_bindings/manager.h"
#include "components/cast/message_port/message_port_cast.h"
#include "components/cast/named_message_port_connector/grit/named_message_port_connector_resources.h"
#include "ui/base/resource/resource_bundle.h"
......@@ -45,10 +46,16 @@ NamedMessagePortConnectorCast::~NamedMessagePortConnectorCast() = default;
void NamedMessagePortConnectorCast::OnPageLoaded() {
// Send the port connection message to the page once it is loaded.
blink::WebMessagePort::Message connect_message = GetConnectMessage();
cast_web_contents_->PostMessageToMainFrame(
"*", base::UTF16ToUTF8(connect_message.data),
std::move(connect_message.ports));
std::string connect_message;
std::unique_ptr<cast_api_bindings::MessagePort> port;
GetConnectMessage(&connect_message, &port);
std::vector<blink::WebMessagePort> ports;
ports.push_back(
cast_api_bindings::MessagePortCast::FromMessagePort(port.get())
->TakePort());
cast_web_contents_->PostMessageToMainFrame("*", connect_message,
std::move(ports));
}
} // namespace bindings
......
......@@ -15,11 +15,7 @@ source_set("manager") {
deps = [
"//base",
"//components/cast:export",
"//third_party/blink/public/common",
]
defines = [ "CAST_COMPONENT_IMPLEMENTATION" ]
public_deps = [
"//components/cast/message_port",
"//mojo/public/cpp/bindings",
]
public_deps = [ "//components/cast/message_port" ]
}
include_rules = [
"+third_party/blink/public/common/messaging",
]
......@@ -22,41 +22,19 @@ void Manager::RegisterPortHandler(base::StringPiece port_name,
DCHECK(result.second);
}
void Manager::RegisterPortHandler(base::StringPiece port_name,
MessagePortProxyConnectedHandler handler) {
auto result = port_proxy_handlers_.try_emplace(port_name, std::move(handler));
DCHECK(result.second);
}
void Manager::UnregisterPortHandler(base::StringPiece port_name) {
size_t deleted = port_handlers_.erase(port_name);
deleted += port_proxy_handlers_.erase(port_name);
DCHECK_EQ(deleted, 1u);
}
bool Manager::OnPortConnected(base::StringPiece port_name,
blink::WebMessagePort port) {
if (!port.IsValid())
return false;
auto handler = port_handlers_.find(port_name);
if (handler == port_handlers_.end()) {
LOG(ERROR) << "No handler found for port " << port_name << ".";
return false;
}
handler->second.Run(std::move(port));
return true;
}
bool Manager::OnPortConnected(
base::StringPiece port_name,
std::unique_ptr<cast_api_bindings::MessagePort> port) {
if (!port)
return false;
auto handler = port_proxy_handlers_.find(port_name);
if (handler == port_proxy_handlers_.end()) {
auto handler = port_handlers_.find(port_name);
if (handler == port_handlers_.end()) {
LOG(ERROR) << "No handler found for port " << port_name << ".";
return false;
}
......
......@@ -13,7 +13,6 @@
#include "base/strings/string_piece.h"
#include "components/cast/cast_component_export.h"
#include "components/cast/message_port/message_port.h"
#include "third_party/blink/public/common/messaging/web_message_port.h"
namespace cast_api_bindings {
......@@ -21,28 +20,18 @@ namespace cast_api_bindings {
// and to register handlers for communication with the content.
class CAST_COMPONENT_EXPORT Manager {
public:
// TODO(crbug.com/1135379): Deprecated; remove or redefine after fixing
// downstream dependencies
using MessagePortConnectedHandler =
base::RepeatingCallback<void(blink::WebMessagePort)>;
using MessagePortProxyConnectedHandler = base::RepeatingCallback<void(
using MessagePortConnectedHandler = base::RepeatingCallback<void(
std::unique_ptr<cast_api_bindings::MessagePort>)>;
Manager();
virtual ~Manager();
// TODO(crbug.com/1135379): Deprecated; remove after fixing downstream
// dependencies
void RegisterPortHandler(base::StringPiece port_name,
MessagePortConnectedHandler handler);
// Registers a |handler| which will receive MessagePorts originating from
// the frame's web content. |port_name| is an alphanumeric string that is
// consistent across JS and native code.
// All handlers must be Unregistered() before |this| is destroyed.
void RegisterPortHandler(base::StringPiece port_name,
MessagePortProxyConnectedHandler handler);
MessagePortConnectedHandler handler);
// Unregisters a previously registered handler.
// The owner of Manager is responsible for ensuring that all
......@@ -55,10 +44,6 @@ class CAST_COMPONENT_EXPORT Manager {
base::StringPiece binding_script) = 0;
protected:
// TODO(crbug.com/1135379): Deprecated; remove after fixing downstream
// dependencies
bool OnPortConnected(base::StringPiece port_name, blink::WebMessagePort port);
// Called by platform-specific implementations when the content requests a
// connection to |port_name|.
// Returns |false| if the port was invalid or not registered in advance, at
......@@ -67,13 +52,8 @@ class CAST_COMPONENT_EXPORT Manager {
std::unique_ptr<cast_api_bindings::MessagePort> port);
private:
// TODO(crbug.com/1135379): Deprecated; remove after fixing downstream
// dependencies
base::flat_map<std::string, MessagePortConnectedHandler> port_handlers_;
base::flat_map<std::string, MessagePortProxyConnectedHandler>
port_proxy_handlers_;
DISALLOW_COPY_AND_ASSIGN(Manager);
};
......
......@@ -6,6 +6,7 @@
#include <string>
#include "base/bind.h"
#include "base/logging.h"
#include "components/cast/api_bindings/manager.h"
......
......@@ -32,3 +32,15 @@ source_set("message_port") {
deps += [ "//third_party/blink/public/common" ]
}
}
source_set("test_message_port_receiver") {
testonly = true
sources = [
"test_message_port_receiver.cc",
"test_message_port_receiver.h",
]
deps = [
":message_port",
"//base",
]
}
......@@ -23,13 +23,13 @@ class MessagePortCast : public cast_api_bindings::MessagePort,
static std::unique_ptr<MessagePort> Create(blink::WebMessagePort&& port);
private:
// Gets the implementation of |port| for callers who know its platform type.
static MessagePortCast* FromMessagePort(MessagePort* port);
// Retrieves the platform-specific port and invalidates this object.
blink::WebMessagePort TakePort();
private:
// cast_api_bindings::MessagePort implementation
bool PostMessage(base::StringPiece message) final;
bool PostMessageWithTransferables(
......
......@@ -5,6 +5,7 @@
#include "components/cast/message_port/message_port_fuchsia.h"
#include "base/fuchsia/fuchsia_logging.h"
#include "base/notreached.h"
#include "fuchsia/base/mem_buffer_util.h"
#include "fuchsia/fidl/chromium/cast/cpp/fidl.h"
......@@ -22,13 +23,20 @@ class MessagePortFuchsiaClient : public MessagePortFuchsia {
~MessagePortFuchsiaClient() override {}
// Invalidates the port an returns the original InterfaceHandle.
fidl::InterfaceHandle<::fuchsia::web::MessagePort> TakeHandle() {
// MessagePortFuchsia implementation.
fidl::InterfaceHandle<::fuchsia::web::MessagePort> TakeClientHandle() final {
DCHECK(!receiver_);
DCHECK(port_.is_bound());
return port_.Unbind();
}
fidl::InterfaceRequest<::fuchsia::web::MessagePort> TakeServiceRequest()
final {
NOTREACHED();
return {};
}
// MessagePort implementation.
void SetReceiver(cast_api_bindings::MessagePort::Receiver* receiver) final {
DCHECK(receiver);
DCHECK(!receiver_);
......@@ -108,13 +116,18 @@ class MessagePortFuchsiaServer : public MessagePortFuchsia,
~MessagePortFuchsiaServer() override {}
// Invalidates the port an returns the original InterfaceRequest.
fidl::InterfaceRequest<::fuchsia::web::MessagePort> TakeRequest() {
DCHECK(!receiver_);
DCHECK(binding_.is_bound());
// MessagePortFuchsia implementation.
fidl::InterfaceHandle<::fuchsia::web::MessagePort> TakeClientHandle() final {
NOTREACHED();
return {};
}
fidl::InterfaceRequest<::fuchsia::web::MessagePort> TakeServiceRequest()
final {
return binding_.Unbind();
}
// MessagePort implementation.
void SetReceiver(cast_api_bindings::MessagePort::Receiver* receiver) final {
DCHECK(receiver);
DCHECK(!receiver_);
......@@ -218,12 +231,12 @@ fuchsia::web::WebMessage MessagePortFuchsia::CreateWebMessage(
message_fidl.set_data(cr_fuchsia::MemBufferFromString(message.as_string(),
message.as_string()));
if (!ports.empty()) {
PortType expected_port_type = FromMessagePort(ports[0].get())->port_type();
PortType expected_port_type = FromMessagePort(ports[0].get())->port_type_;
std::vector<fuchsia::web::IncomingTransferable> incoming_transferables;
std::vector<fuchsia::web::OutgoingTransferable> receiver_transferables;
for (auto& port : ports) {
MessagePortFuchsia* port_fuchsia = FromMessagePort(port.get());
PortType port_type = port_fuchsia->port_type();
PortType port_type = port_fuchsia->port_type_;
DCHECK_EQ(expected_port_type, port_type)
<< "Only one implementation of MessagePortFuchsia can be transmitted "
......@@ -237,7 +250,7 @@ fuchsia::web::WebMessage MessagePortFuchsia::CreateWebMessage(
fuchsia::web::IncomingTransferable in;
in.set_message_port(
reinterpret_cast<MessagePortFuchsiaClient*>(port_fuchsia)
->TakeHandle());
->TakeClientHandle());
incoming_transferables.emplace_back(std::move(in));
break;
}
......@@ -245,7 +258,7 @@ fuchsia::web::WebMessage MessagePortFuchsia::CreateWebMessage(
fuchsia::web::OutgoingTransferable out;
out.set_message_port(
reinterpret_cast<MessagePortFuchsiaServer*>(port_fuchsia)
->TakeRequest());
->TakeServiceRequest());
receiver_transferables.emplace_back(std::move(out));
break;
}
......@@ -263,10 +276,6 @@ MessagePortFuchsia::MessagePortFuchsia(PortType port_type)
: receiver_(nullptr), port_type_(port_type) {}
MessagePortFuchsia::~MessagePortFuchsia() = default;
MessagePortFuchsia::PortType MessagePortFuchsia::port_type() const {
return port_type_;
}
base::Optional<fuchsia::web::FrameError>
MessagePortFuchsia::ReceiveMessageFromFidl(fuchsia::web::WebMessage message) {
DCHECK(receiver_);
......@@ -331,4 +340,5 @@ bool MessagePortFuchsia::PostMessageWithTransferables(
return true;
}
} // namespace cast_api_bindings
......@@ -30,6 +30,18 @@ class MessagePortFuchsia : public cast_api_bindings::MessagePort {
static std::unique_ptr<MessagePort> Create(
fidl::InterfaceRequest<::fuchsia::web::MessagePort> port);
// Gets the implementation of |port| for callers who know its platform type.
static MessagePortFuchsia* FromMessagePort(MessagePort* port);
// Returns the platform-specific port resources and invalidates this object.
// The caller is responsible for choosing the take method which is appropriate
// to the underlying FIDL resource. Attempting to take the wrong resource will
// produce a DCHECK failure.
virtual fidl::InterfaceHandle<::fuchsia::web::MessagePort>
TakeClientHandle() = 0;
virtual fidl::InterfaceRequest<::fuchsia::web::MessagePort>
TakeServiceRequest() = 0;
protected:
// Represents whether a MessagePortFuchsia was created from an InterfaceHandle
// (PortType::HANDLE) or InterfaceRequest (PortType::REQUEST)
......@@ -38,7 +50,7 @@ class MessagePortFuchsia : public cast_api_bindings::MessagePort {
REQUEST = 2,
};
MessagePortFuchsia(PortType port_type);
explicit MessagePortFuchsia(PortType port_type);
// Creates a fuchsia::web::WebMessage containing |message| and transferring
// |ports|
......@@ -54,10 +66,6 @@ class MessagePortFuchsia : public cast_api_bindings::MessagePort {
base::Optional<fuchsia::web::FrameError> ReceiveMessageFromFidl(
fuchsia::web::WebMessage message);
// Retrieves the platform-specific port and invalidates this object.
fidl::InterfaceHandle<::fuchsia::web::MessagePort> TakeHandle();
fidl::InterfaceRequest<::fuchsia::web::MessagePort> TakeRequest();
void OnZxError(zx_status_t status);
void ReportPipeError();
......@@ -71,11 +79,6 @@ class MessagePortFuchsia : public cast_api_bindings::MessagePort {
base::circular_deque<fuchsia::web::WebMessage> message_queue_;
private:
// Gets the implementation of |port| for callers who know its platform type.
static MessagePortFuchsia* FromMessagePort(MessagePort* port);
PortType port_type() const;
const PortType port_type_;
};
......
// Copyright 2020 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 "components/cast/message_port/test_message_port_receiver.h"
#include "base/run_loop.h"
namespace cast_api_bindings {
TestMessagePortReceiver::TestMessagePortReceiver() = default;
TestMessagePortReceiver::~TestMessagePortReceiver() = default;
bool TestMessagePortReceiver::RunUntilMessageCountEqual(size_t message_count) {
base::RunLoop run_loop;
on_receive_satisfied_ = run_loop.QuitClosure();
message_count_target_ = message_count;
run_loop.Run();
return message_count_target_ == message_count;
}
void TestMessagePortReceiver::RunUntilDisconnected() {
base::RunLoop run_loop;
on_disconnect_ = run_loop.QuitClosure();
run_loop.Run();
}
bool TestMessagePortReceiver::OnMessage(
base::StringPiece message,
std::vector<std::unique_ptr<MessagePort>> ports) {
buffer_.push_back(std::make_pair(message.as_string(), std::move(ports)));
if (message_count_target_ == buffer_.size()) {
DCHECK(on_receive_satisfied_);
std::move(on_receive_satisfied_).Run();
}
return true;
}
void TestMessagePortReceiver::OnPipeError() {
if (on_disconnect_)
std::move(on_disconnect_).Run();
}
} // namespace cast_api_bindings
// Copyright 2020 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 COMPONENTS_CAST_MESSAGE_PORT_TEST_MESSAGE_PORT_RECEIVER_H_
#define COMPONENTS_CAST_MESSAGE_PORT_TEST_MESSAGE_PORT_RECEIVER_H_
#include <memory>
#include <vector>
#include "base/callback.h"
#include "base/strings/string_piece.h"
#include "components/cast/message_port/message_port.h"
namespace cast_api_bindings {
class TestMessagePortReceiver
: public cast_api_bindings::MessagePort::Receiver {
public:
TestMessagePortReceiver();
~TestMessagePortReceiver() override;
TestMessagePortReceiver(const TestMessagePortReceiver&) = delete;
TestMessagePortReceiver& operator=(const TestMessagePortReceiver&) = delete;
// Spins a RunLoop until |buffer_| has |message_count| messages.
bool RunUntilMessageCountEqual(size_t message_count);
// Spins a RunLoop until the associated MessagePort is disconnected.
void RunUntilDisconnected();
std::vector<
std::pair<std::string, std::vector<std::unique_ptr<MessagePort>>>>&
buffer() {
return buffer_;
}
private:
// MessagePort::Receiver implementation.
bool OnMessage(base::StringPiece message,
std::vector<std::unique_ptr<MessagePort>> ports) final;
void OnPipeError() final;
std::vector<std::pair<std::string, std::vector<std::unique_ptr<MessagePort>>>>
buffer_;
size_t message_count_target_ = 0;
base::OnceClosure on_receive_satisfied_;
base::OnceClosure on_disconnect_;
};
} // namespace cast_api_bindings
#endif // COMPONENTS_CAST_MESSAGE_PORT_TEST_MESSAGE_PORT_RECEIVER_H_
......@@ -13,12 +13,10 @@ source_set("named_message_port_connector") {
deps = [
"//base",
"//components/cast:export",
"//components/cast/message_port",
]
public_deps = [
":resources",
"//third_party/blink/public/common",
]
public_deps = [ ":resources" ]
}
grit("resources") {
......
......@@ -25,35 +25,32 @@ void NamedMessagePortConnector::RegisterPortHandler(
// Receives the MessagePort and forwards ports to their corresponding binding
// handlers.
bool NamedMessagePortConnector::OnMessage(
blink::WebMessagePort::Message message) {
if (message.ports.size() != 1) {
base::StringPiece message,
std::vector<std::unique_ptr<MessagePort>> ports) {
if (ports.size() != 1) {
DLOG(FATAL) << "Only one control port should be provided";
return false;
}
// Read the port ID.
base::string16 data_utf16 = std::move(message.data);
std::string binding_id;
if (!base::UTF16ToUTF8(data_utf16.data(), data_utf16.size(), &binding_id))
if (message.empty()) {
DLOG(FATAL) << "No port ID was specified.";
return false;
}
return handler_.Run(binding_id, std::move(message.ports[0]));
return handler_.Run(message, std::move(ports[0]));
}
blink::WebMessagePort::Message NamedMessagePortConnector::GetConnectMessage() {
constexpr char kControlPortConnectMessage[] = "cast.master.connect";
// Pass the control message port into the page as an HTML5 MessageChannel
// message.
auto port_pair = blink::WebMessagePort::CreatePair();
void NamedMessagePortConnector::OnPipeError() {}
control_port_ = std::move(port_pair.first);
control_port_.SetReceiver(this, base::ThreadTaskRunnerHandle::Get());
blink::WebMessagePort::Message connect_message;
connect_message.data = base::UTF8ToUTF16(kControlPortConnectMessage);
connect_message.ports.push_back(std::move(port_pair.second));
return connect_message;
void NamedMessagePortConnector::GetConnectMessage(
std::string* message,
std::unique_ptr<MessagePort>* port) {
constexpr char kControlPortConnectMessage[] = "cast.master.connect";
std::unique_ptr<MessagePort> control_port_for_web_engine;
MessagePort::CreatePair(&control_port_, port);
*message = kControlPortConnectMessage;
control_port_->SetReceiver(this);
}
} // namespace cast_api_bindings
......@@ -7,7 +7,7 @@
#include "base/callback.h"
#include "base/strings/string_piece.h"
#include "third_party/blink/public/common/messaging/web_message_port.h"
#include "components/cast/message_port/message_port.h"
namespace cast_api_bindings {
......@@ -16,15 +16,13 @@ namespace cast_api_bindings {
// Platform specific details, such as how the script resources are injected, and
// how the connection message is posted to the page, are delegated to the
// caller.
// TODO(crbug.com/1126571): Migrate off Blink::WebMessagePort to a
// platform-agnostic MessagePort abstraction.
class NamedMessagePortConnector
: public blink::WebMessagePort::MessageReceiver {
class NamedMessagePortConnector : public MessagePort::Receiver {
public:
// Signature of callback to be invoked when a port is connected.
// The callback should return true if the connection request was valid.
using PortConnectedCallback =
base::RepeatingCallback<bool(base::StringPiece, blink::WebMessagePort)>;
base::RepeatingCallback<bool(base::StringPiece,
std::unique_ptr<MessagePort>)>;
NamedMessagePortConnector();
~NamedMessagePortConnector() override;
......@@ -36,17 +34,20 @@ class NamedMessagePortConnector
// Sets the callback which will be invoked when a port is connected.
void RegisterPortHandler(PortConnectedCallback handler);
// Returns a connection message which should be posted to the page on
// every navigation.
// Calling this method will drop any preexisting connections made to the page.
blink::WebMessagePort::Message GetConnectMessage();
// Returns a data payload and MessagePort which, when posted into a web
// content main frame, will establish a connection between |this| and the
// NamedMessagePortConnector JavaScript module.
void GetConnectMessage(std::string* message,
std::unique_ptr<MessagePort>* port);
private:
// blink::WebMessagePort::MessageReceiver implementation:
bool OnMessage(blink::WebMessagePort::Message message) override;
// MessagePort::Receiver implementation.
bool OnMessage(base::StringPiece message,
std::vector<std::unique_ptr<MessagePort>> ports) final;
void OnPipeError() final;
PortConnectedCallback handler_;
blink::WebMessagePort control_port_;
std::unique_ptr<MessagePort> control_port_;
};
} // namespace cast_api_bindings
......
......@@ -64,6 +64,8 @@ source_set("cast_runner_core") {
"cast/cast_runner_switches.h",
"cast/cast_streaming.cc",
"cast/cast_streaming.h",
"cast/create_web_message.cc",
"cast/create_web_message.h",
"cast/named_message_port_connector_fuchsia.cc",
"cast/named_message_port_connector_fuchsia.h",
"cast/pending_cast_component.cc",
......@@ -76,6 +78,7 @@ source_set("cast_runner_core") {
]
deps = [
"//base",
"//components/cast/message_port",
"//components/cast/named_message_port_connector:named_message_port_connector",
"//fuchsia/base",
"//fuchsia/base:modular",
......@@ -85,16 +88,18 @@ source_set("cast_runner_core") {
"//url",
]
# TODO(crbug.com/1131102): Remove dep when MessagePortProxy lands, and add assertions to ensure
# that Blink indirect deps don't creep back in.
deps += [ "//fuchsia/base:message_port" ]
public_deps = [
":common",
"//fuchsia:cast_fidl",
"//third_party/fuchsia-sdk/sdk/fidl/fuchsia.legacymetrics",
"//third_party/fuchsia-sdk/sdk/fidl/fuchsia.web",
]
# Keep CastRunner trim by ensuring that large browser dependencies don't creep in.
assert_no_deps = [
"//content/public/common",
"//third_party/blink/public/common",
]
visibility = [ ":*" ]
}
......@@ -106,8 +111,6 @@ executable("cast_runner_exe") {
":common",
"//base",
"//fuchsia/base",
"//mojo/core/embedder", # TODO(crbug.com/1126571): Remove when
# MessagePortProxy lands.
]
data_deps = [ ":cast_runner_core" ]
......@@ -118,18 +121,6 @@ cr_fuchsia_package("cast_runner_pkg") {
binary = ":cast_runner_exe"
package_name_override = "cast_runner"
manifest = "cast/cast_runner.cmx"
# TODO(crbug.com/1131102): Remove these exclusions when MessagePortProxy lands.
excluded_files = [
"lib/libEGL.so",
"lib/libfuchsia_egl.so",
"lib/libGLESv2.so",
"lib/libswiftshader_libEGL.so",
"lib/libswiftshader_libGLESv2.so",
"lib/libtrace-engine.so",
"lib/libvulkan.so",
"lib/VkLayer_image_pipe_swapchain.so",
]
}
fuchsia_package_runner("cast_runner") {
......@@ -185,9 +176,8 @@ test("cast_runner_integration_tests") {
":cast_runner_test_core",
"//base/test:run_all_unittests",
"//base/test:test_support",
"//components/cast/message_port",
"//fuchsia/base:test_support",
"//mojo/core/embedder", # TODO(crbug.com/1126571): Remove when
# MessagePortProxy lands.
"//net:test_support",
"//testing/gtest",
"//third_party/fuchsia-sdk/sdk/fidl/fuchsia.camera3",
......@@ -220,10 +210,11 @@ test("cast_runner_browsertests") {
":cast_runner_core",
":cast_runner_test_core",
"//base/test:test_support",
"//components/cast/message_port",
"//components/cast/message_port:test_message_port_receiver",
"//content/public/browser",
"//content/test:test_support",
"//fuchsia/base",
"//fuchsia/base:message_port",
"//fuchsia/base:test_support",
"//fuchsia/engine:browsertest_core",
"//testing/gmock",
......@@ -265,6 +256,7 @@ test("web_runner_integration_tests") {
"//base",
"//base/test:run_all_unittests",
"//base/test:test_support",
"//components/cast/message_port",
"//fuchsia/base:modular",
"//net:test_support",
"//testing/gtest",
......
include_rules = [
"+components/cast/message_port",
"+components/cast/named_message_port_connector",
"+content/public/test",
"+mojo/core/embedder",
]
......@@ -9,7 +9,7 @@
#include "base/bind.h"
#include "base/fuchsia/fuchsia_logging.h"
#include "base/strings/string_piece.h"
#include "fuchsia/base/message_port.h"
#include "components/cast/message_port/message_port_fuchsia.h"
namespace {
......@@ -89,14 +89,16 @@ bool ApiBindingsClient::HasBindings() const {
return bindings_.has_value();
}
bool ApiBindingsClient::OnPortConnected(base::StringPiece port_name,
blink::WebMessagePort port) {
bool ApiBindingsClient::OnPortConnected(
base::StringPiece port_name,
std::unique_ptr<cast_api_bindings::MessagePort> port) {
if (!bindings_service_)
return false;
bindings_service_->Connect(
port_name.as_string(),
cr_fuchsia::FidlMessagePortFromBlink(std::move(port)));
cast_api_bindings::MessagePortFuchsia::FromMessagePort(port.get())
->TakeClientHandle());
return true;
}
......
......@@ -10,6 +10,7 @@
#include "base/macros.h"
#include "base/optional.h"
#include "components/cast/message_port/message_port.h"
#include "components/cast/named_message_port_connector/named_message_port_connector.h"
#include "fuchsia/fidl/chromium/cast/cpp/fidl.h"
......@@ -45,7 +46,8 @@ class ApiBindingsClient {
// TODO(crbug.com/1082821): Move this method back to private once the Cast
// Streaming Receiver component has been implemented.
// Called when |connector_| has connected a port.
bool OnPortConnected(base::StringPiece port_name, blink::WebMessagePort port);
bool OnPortConnected(base::StringPiece port_name,
std::unique_ptr<cast_api_bindings::MessagePort> port);
private:
// Called when ApiBindings::GetAll() has responded.
......
......@@ -10,15 +10,16 @@
#include "base/files/file_util.h"
#include "base/path_service.h"
#include "base/test/bind_test_util.h"
#include "components/cast/message_port/message_port_fuchsia.h"
#include "content/public/test/browser_test.h"
#include "fuchsia/base/fit_adapter.h"
#include "fuchsia/base/frame_test_util.h"
#include "fuchsia/base/mem_buffer_util.h"
#include "fuchsia/base/message_port.h"
#include "fuchsia/base/result_receiver.h"
#include "fuchsia/base/test_navigation_listener.h"
#include "fuchsia/engine/test/web_engine_browser_test.h"
#include "fuchsia/runners/cast/api_bindings_client.h"
#include "fuchsia/runners/cast/create_web_message.h"
#include "fuchsia/runners/cast/named_message_port_connector_fuchsia.h"
#include "fuchsia/runners/cast/test_api_bindings.h"
#include "testing/gtest/include/gtest/gtest.h"
......@@ -101,15 +102,17 @@ IN_PROC_BROWSER_TEST_F(ApiBindingsClientTest, EndToEnd) {
EXPECT_TRUE(cr_fuchsia::LoadUrlAndExpectResponse(
controller_.get(), fuchsia::web::LoadUrlParams(), test_url.spec()));
navigation_listener_.RunUntilUrlEquals(test_url);
frame_->PostMessage("*",
std::move(*cr_fuchsia::FidlWebMessageFromBlink(
connector_->GetConnectMessage(),
cr_fuchsia::TransferableHostType::kRemote)),
[&post_message_response_closure](
fuchsia::web::Frame_PostMessage_Result result) {
ASSERT_TRUE(result.is_response());
post_message_response_closure.Run();
});
std::string connect_message;
std::unique_ptr<cast_api_bindings::MessagePort> connect_port;
connector_->GetConnectMessage(&connect_message, &connect_port);
frame_->PostMessage(
"*", CreateWebMessage(connect_message, std::move(connect_port)),
[&post_message_response_closure](
fuchsia::web::Frame_PostMessage_Result result) {
ASSERT_TRUE(result.is_response());
post_message_response_closure.Run();
});
// Connect to the echo service hosted by the page and send a ping to it.
fuchsia::web::WebMessage message;
......
......@@ -16,12 +16,13 @@
#include "base/fuchsia/fuchsia_logging.h"
#include "base/path_service.h"
#include "base/task/current_thread.h"
#include "components/cast/message_port/message_port_fuchsia.h"
#include "fuchsia/base/agent_manager.h"
#include "fuchsia/base/mem_buffer_util.h"
#include "fuchsia/base/message_port.h"
#include "fuchsia/fidl/chromium/cast/cpp/fidl.h"
#include "fuchsia/runners/cast/cast_runner.h"
#include "fuchsia/runners/cast/cast_streaming.h"
#include "fuchsia/runners/cast/create_web_message.h"
#include "fuchsia/runners/common/web_component.h"
namespace {
......@@ -100,26 +101,21 @@ void CastComponent::StartComponent() {
// component has been implemented.
// Register the MessagePort for the Cast Streaming Receiver.
fidl::InterfaceHandle<fuchsia::web::MessagePort> message_port;
fuchsia::web::WebMessage message;
message.set_data(cr_fuchsia::MemBufferFromString("", "empty_message"));
fuchsia::web::OutgoingTransferable outgoing_transferable;
outgoing_transferable.set_message_port(message_port.NewRequest());
std::vector<fuchsia::web::OutgoingTransferable> outgoing_transferables;
outgoing_transferables.push_back(std::move(outgoing_transferable));
message.set_outgoing_transfer(std::move(outgoing_transferables));
std::unique_ptr<cast_api_bindings::MessagePort> message_port_for_web_engine;
std::unique_ptr<cast_api_bindings::MessagePort> message_port_for_agent;
cast_api_bindings::MessagePort::CreatePair(&message_port_for_agent,
&message_port_for_web_engine);
frame()->PostMessage(
kCastStreamingMessagePortOrigin, std::move(message),
kCastStreamingMessagePortOrigin,
CreateWebMessage("", std::move(message_port_for_web_engine)),
[this](fuchsia::web::Frame_PostMessage_Result result) {
if (result.is_err()) {
DestroyComponent(kBindingsFailureExitCode,
fuchsia::sys::TerminationReason::INTERNAL_ERROR);
}
});
api_bindings_client_->OnPortConnected(
kCastStreamingMessagePortName,
cr_fuchsia::BlinkMessagePortFromFidl(std::move(message_port)));
api_bindings_client_->OnPortConnected(kCastStreamingMessagePortName,
std::move(message_port_for_agent));
}
api_bindings_client_->AttachToFrame(
......@@ -187,14 +183,16 @@ void CastComponent::OnNavigationStateChanged(
OnNavigationStateChangedCallback callback) {
if (change.has_is_main_document_loaded() &&
change.is_main_document_loaded()) {
std::string connect_message;
std::unique_ptr<cast_api_bindings::MessagePort> connect_port;
connector_->GetConnectMessage(&connect_message, &connect_port);
// Send the NamedMessagePortConnector handshake to the page.
frame()->PostMessage("*",
*cr_fuchsia::FidlWebMessageFromBlink(
connector_->GetConnectMessage(),
cr_fuchsia::TransferableHostType::kRemote),
[](fuchsia::web::Frame_PostMessage_Result result) {
DCHECK(result.is_response());
});
frame()->PostMessage(
"*", CreateWebMessage(connect_message, std::move(connect_port)),
[](fuchsia::web::Frame_PostMessage_Result result) {
DCHECK(result.is_response());
});
}
WebComponent::OnNavigationStateChanged(std::move(change),
......
......@@ -43,7 +43,6 @@
#include "fuchsia/runners/cast/cast_runner_switches.h"
#include "fuchsia/runners/cast/fake_application_config_manager.h"
#include "fuchsia/runners/cast/test_api_bindings.h"
#include "mojo/core/embedder/embedder.h"
#include "net/test/embedded_test_server/default_handlers.h"
#include "net/test/embedded_test_server/http_request.h"
#include "testing/gtest/include/gtest/gtest.h"
......@@ -256,8 +255,6 @@ class CastRunnerIntegrationTest : public testing::Test {
CastRunnerIntegrationTest& operator=(const CastRunnerIntegrationTest&) =
delete;
void SetUp() override { mojo::core::Init(); }
void TearDown() override {
if (component_controller_)
ShutdownComponent();
......
// Copyright 2020 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/runners/cast/create_web_message.h"
#include "components/cast/message_port/message_port_fuchsia.h"
#include "fuchsia/base/mem_buffer_util.h"
fuchsia::web::WebMessage CreateWebMessage(
base::StringPiece message,
std::unique_ptr<cast_api_bindings::MessagePort> port) {
fuchsia::web::WebMessage web_message;
web_message.set_data(cr_fuchsia::MemBufferFromString(message, "msg"));
if (port) {
fuchsia::web::OutgoingTransferable outgoing_transferable;
outgoing_transferable.set_message_port(
cast_api_bindings::MessagePortFuchsia::FromMessagePort(port.get())
->TakeServiceRequest());
std::vector<fuchsia::web::OutgoingTransferable> outgoing_transferables;
outgoing_transferables.push_back(std::move(outgoing_transferable));
web_message.set_outgoing_transfer(std::move(outgoing_transferables));
}
return web_message;
}
// Copyright 2020 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_RUNNERS_CAST_CREATE_WEB_MESSAGE_H_
#define FUCHSIA_RUNNERS_CAST_CREATE_WEB_MESSAGE_H_
#include <fuchsia/web/cpp/fidl.h>
#include <memory>
#include "base/strings/string_piece.h"
#include "components/cast/message_port/message_port.h"
// Utility function for creating a fuchsia.web.WebMessage with the payload
// |message| and an optional transferred |port|.
fuchsia::web::WebMessage CreateWebMessage(
base::StringPiece message,
std::unique_ptr<cast_api_bindings::MessagePort> port);
#endif // FUCHSIA_RUNNERS_CAST_CREATE_WEB_MESSAGE_H_
......@@ -20,7 +20,6 @@
#include "fuchsia/base/inspect.h"
#include "fuchsia/runners/cast/cast_runner.h"
#include "fuchsia/runners/cast/cast_runner_switches.h"
#include "mojo/core/embedder/embedder.h"
namespace {
......@@ -68,8 +67,6 @@ int main(int argc, char** argv) {
*base::CommandLine::ForCurrentProcess()))
<< "Failed to initialize logging.";
mojo::core::Init();
cr_fuchsia::RegisterFuchsiaDirScheme();
sys::OutgoingDirectory* const outgoing_directory =
......
......@@ -9,20 +9,26 @@
#include "base/files/file_util.h"
#include "base/macros.h"
#include "base/path_service.h"
#include "components/cast/message_port/message_port_fuchsia.h"
#include "components/cast/message_port/test_message_port_receiver.h"
#include "content/public/test/browser_test.h"
#include "fuchsia/base/fit_adapter.h"
#include "fuchsia/base/frame_test_util.h"
#include "fuchsia/base/mem_buffer_util.h"
#include "fuchsia/base/message_port.h"
#include "fuchsia/base/result_receiver.h"
#include "fuchsia/base/test_navigation_listener.h"
#include "fuchsia/engine/test/web_engine_browser_test.h"
#include "fuchsia/runners/cast/create_web_message.h"
#include "fuchsia/runners/cast/named_message_port_connector_fuchsia.h"
#include "testing/gmock/include/gmock/gmock-matchers.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/url_constants.h"
using CastMessagePort = std::unique_ptr<cast_api_bindings::MessagePort>;
namespace {
class NamedMessagePortConnectorFuchsiaTest
: public cr_fuchsia::WebEngineBrowserTest {
public:
......@@ -52,13 +58,14 @@ class NamedMessagePortConnectorFuchsiaTest
callback) {
if (change.has_is_main_document_loaded() &&
change.is_main_document_loaded()) {
frame_->PostMessage("*",
std::move(*cr_fuchsia::FidlWebMessageFromBlink(
connector_->GetConnectMessage(),
cr_fuchsia::TransferableHostType::kRemote)),
[](fuchsia::web::Frame_PostMessage_Result result) {
DCHECK(result.is_response());
});
std::string connect_message;
CastMessagePort connect_port;
connector_->GetConnectMessage(&connect_message, &connect_port);
frame_->PostMessage(
"*", CreateWebMessage(connect_message, std::move(connect_port)),
[](fuchsia::web::Frame_PostMessage_Result result) {
DCHECK(result.is_response());
});
}
// Allow the TestNavigationListener's usual navigation event processing flow
......@@ -82,15 +89,14 @@ IN_PROC_BROWSER_TEST_F(NamedMessagePortConnectorFuchsiaTest, EndToEnd) {
frame_->GetNavigationController(controller.NewRequest());
std::string received_port_name;
fidl::InterfaceHandle<fuchsia::web::MessagePort> received_port;
CastMessagePort received_port;
base::RunLoop receive_port_run_loop;
connector_->RegisterPortHandler(base::BindRepeating(
[](std::string* received_port_name,
fidl::InterfaceHandle<fuchsia::web::MessagePort>* received_port,
[](std::string* received_port_name, CastMessagePort* received_port,
base::RunLoop* receive_port_run_loop, base::StringPiece port_name,
blink::WebMessagePort port) -> bool {
CastMessagePort port) -> bool {
*received_port_name = port_name.as_string();
*received_port = cr_fuchsia::FidlMessagePortFromBlink(std::move(port));
*received_port = std::move(port);
receive_port_run_loop->Quit();
return true;
},
......@@ -105,43 +111,23 @@ IN_PROC_BROWSER_TEST_F(NamedMessagePortConnectorFuchsiaTest, EndToEnd) {
receive_port_run_loop.Run();
EXPECT_EQ(received_port_name, "echo");
fuchsia::web::MessagePortPtr message_port = received_port.Bind();
fuchsia::web::WebMessage msg;
msg.set_data(cr_fuchsia::MemBufferFromString("ping", "test"));
cr_fuchsia::ResultReceiver<fuchsia::web::MessagePort_PostMessage_Result>
post_result;
message_port->PostMessage(
std::move(msg),
cr_fuchsia::CallbackToFitFunction(post_result.GetReceiveCallback()));
std::vector<std::string> test_messages = {"early 1", "early 2", "ack ping"};
for (std::string expected_msg : test_messages) {
base::RunLoop run_loop;
cr_fuchsia::ResultReceiver<fuchsia::web::WebMessage> message_receiver(
run_loop.QuitClosure());
message_port->ReceiveMessage(cr_fuchsia::CallbackToFitFunction(
message_receiver.GetReceiveCallback()));
run_loop.Run();
std::string data;
ASSERT_TRUE(message_receiver->has_data());
ASSERT_TRUE(
cr_fuchsia::StringFromMemBuffer(message_receiver->data(), &data));
EXPECT_EQ(data, expected_msg);
}
cast_api_bindings::TestMessagePortReceiver test_receiver;
received_port->SetReceiver(&test_receiver);
received_port->PostMessage("ping");
ASSERT_TRUE(test_receiver.RunUntilMessageCountEqual(3));
EXPECT_EQ(test_receiver.buffer()[0].first, "early 1");
EXPECT_EQ(test_receiver.buffer()[1].first, "early 2");
EXPECT_EQ(test_receiver.buffer()[2].first, "ack ping");
EXPECT_TRUE(received_port->CanPostMessage());
// Ensure that the MessagePort is dropped when navigating away.
{
base::RunLoop run_loop;
message_port.set_error_handler([&run_loop](zx_status_t status) {
EXPECT_EQ(ZX_ERR_PEER_CLOSED, status);
run_loop.Quit();
});
EXPECT_TRUE(cr_fuchsia::LoadUrlAndExpectResponse(
controller.get(), fuchsia::web::LoadUrlParams(), "about:blank"));
run_loop.Run();
}
EXPECT_TRUE(cr_fuchsia::LoadUrlAndExpectResponse(
controller.get(), fuchsia::web::LoadUrlParams(), "about:blank"));
test_receiver.RunUntilDisconnected();
EXPECT_FALSE(received_port->CanPostMessage());
}
// Tests that the NamedMessagePortConnectorFuchsia can receive more than one
......@@ -156,50 +142,34 @@ IN_PROC_BROWSER_TEST_F(NamedMessagePortConnectorFuchsiaTest, MultiplePorts) {
fuchsia::web::NavigationControllerPtr controller;
frame_->GetNavigationController(controller.NewRequest());
std::vector<fidl::InterfaceHandle<fuchsia::web::MessagePort>> received_ports;
base::RunLoop receive_ports_run_loop;
std::vector<CastMessagePort> received_ports;
base::RunLoop receive_port_run_loop;
connector_->RegisterPortHandler(base::BindRepeating(
[](std::vector<fidl::InterfaceHandle<fuchsia::web::MessagePort>>*
received_ports,
base::RunLoop* receive_ports_run_loop, base::StringPiece,
blink::WebMessagePort port) -> bool {
received_ports->push_back(
cr_fuchsia::FidlMessagePortFromBlink(std::move(port)));
[](std::vector<CastMessagePort>* received_ports,
base::RunLoop* receive_port_run_loop, base::StringPiece port_name,
CastMessagePort port) -> bool {
received_ports->push_back(std::move(port));
if (received_ports->size() == kExpectedPortCount)
receive_ports_run_loop->Quit();
receive_port_run_loop->Quit();
return true;
},
base::Unretained(&received_ports),
base::Unretained(&receive_ports_run_loop)));
base::Unretained(&receive_port_run_loop)));
EXPECT_TRUE(cr_fuchsia::LoadUrlAndExpectResponse(
controller.get(), fuchsia::web::LoadUrlParams(), test_url.spec()));
navigation_listener_.RunUntilUrlEquals(test_url);
receive_ports_run_loop.Run();
for (fidl::InterfaceHandle<fuchsia::web::MessagePort>& message_port :
received_ports) {
fuchsia::web::MessagePortPtr port = message_port.Bind();
fuchsia::web::WebMessage msg;
msg.set_data(cr_fuchsia::MemBufferFromString("ping", "test"));
cr_fuchsia::ResultReceiver<fuchsia::web::MessagePort_PostMessage_Result>
post_result;
port->PostMessage(std::move(msg), cr_fuchsia::CallbackToFitFunction(
post_result.GetReceiveCallback()));
base::RunLoop run_loop;
cr_fuchsia::ResultReceiver<fuchsia::web::WebMessage> message_receiver(
run_loop.QuitClosure());
port->ReceiveMessage(cr_fuchsia::CallbackToFitFunction(
message_receiver.GetReceiveCallback()));
run_loop.Run();
std::string data;
ASSERT_TRUE(message_receiver->has_data());
ASSERT_TRUE(
cr_fuchsia::StringFromMemBuffer(message_receiver->data(), &data));
EXPECT_EQ(data, "ack ping");
receive_port_run_loop.Run();
ASSERT_EQ(received_ports.size(), kExpectedPortCount);
for (CastMessagePort& message_port : received_ports) {
cast_api_bindings::TestMessagePortReceiver test_receiver;
message_port->SetReceiver(&test_receiver);
message_port->PostMessage("ping");
test_receiver.RunUntilMessageCountEqual(1);
EXPECT_EQ(test_receiver.buffer()[0].first, "ack ping");
}
}
} // namespace
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