Commit 4e3dbc1a authored by Wez's avatar Wez Committed by Commit Bot

[Fuchsia] Update CastRunner to use ComponentContext to find services.

Previously CastRunner would look for Agent-provided services (e.g.
CastChannel) in the service namespace supplied on component launch.

If a ComponentContext is found in the service namespace passed to
StartComponent() then the CastRunner will now use that to connect to
the CastAgent to find Cast-specific services.

This requires temporary work-arounds e.g. to fall-back to looking at
the "additional services" provided in the component's StartupInfo,
until we migrate to the new component-manager APIs.

Bug: 920920, 893229
Change-Id: I43aec5c47bc24a0d2a537de621b20fad3342a5f8
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1472333
Commit-Queue: Wez <wez@chromium.org>
Reviewed-by: default avatarKevin Marshall <kmarshall@chromium.org>
Cr-Commit-Position: refs/heads/master@{#638215}
parent 4c871189
...@@ -26,7 +26,7 @@ StartupContext::StartupContext(::fuchsia::sys::StartupInfo startup_info) ...@@ -26,7 +26,7 @@ StartupContext::StartupContext(::fuchsia::sys::StartupInfo startup_info)
} }
} }
// TODO(https://crbug.com/933834): Remove this workaround when we migrate to // TODO(https://crbug.com/933834): Remove these workarounds when we migrate to
// the new component manager. // the new component manager.
if (!incoming_services_ && startup_info_.launch_info.flat_namespace) { if (!incoming_services_ && startup_info_.launch_info.flat_namespace) {
LOG(WARNING) << "Falling back to LaunchInfo namespace"; LOG(WARNING) << "Falling back to LaunchInfo namespace";
...@@ -40,6 +40,28 @@ StartupContext::StartupContext(::fuchsia::sys::StartupInfo startup_info) ...@@ -40,6 +40,28 @@ StartupContext::StartupContext(::fuchsia::sys::StartupInfo startup_info)
} }
} }
} }
if (!incoming_services_ && startup_info_.launch_info.additional_services) {
LOG(WARNING) << "Falling back to additional ServiceList services";
// Construct a ServiceDirectory and publish the additional services into it.
fidl::InterfaceHandle<::fuchsia::io::Directory> incoming_directory;
additional_services_.Bind(
std::move(startup_info_.launch_info.additional_services->provider));
additional_services_directory_ =
std::make_unique<base::fuchsia::ServiceDirectory>(
incoming_directory.NewRequest());
for (auto& name : startup_info_.launch_info.additional_services->names) {
additional_services_directory_->AddServiceUnsafe(
name, base::BindRepeating(
&::fuchsia::sys::ServiceProvider::ConnectToService,
base::Unretained(additional_services_.get()), name));
}
// Publish those services to the caller as |incoming_services_|.
incoming_services_ = std::make_unique<ServiceDirectoryClient>(
fidl::InterfaceHandle<::fuchsia::io::Directory>(
std::move(incoming_directory)));
}
} }
StartupContext::~StartupContext() = default; StartupContext::~StartupContext() = default;
......
...@@ -28,6 +28,7 @@ class BASE_EXPORT StartupContext { ...@@ -28,6 +28,7 @@ class BASE_EXPORT StartupContext {
// Returns the namespace of services published for use by the component. // Returns the namespace of services published for use by the component.
const ServiceDirectoryClient* incoming_services() const { const ServiceDirectoryClient* incoming_services() const {
DCHECK(incoming_services_);
return incoming_services_.get(); return incoming_services_.get();
} }
...@@ -43,6 +44,11 @@ class BASE_EXPORT StartupContext { ...@@ -43,6 +44,11 @@ class BASE_EXPORT StartupContext {
std::unique_ptr<ServiceDirectoryClient> incoming_services_; std::unique_ptr<ServiceDirectoryClient> incoming_services_;
std::unique_ptr<ServiceDirectory> public_services_; std::unique_ptr<ServiceDirectory> public_services_;
// TODO(https://crbug.com/933834): Remove these when we migrate to the new
// component manager APIs.
::fuchsia::sys::ServiceProviderPtr additional_services_;
std::unique_ptr<ServiceDirectory> additional_services_directory_;
DISALLOW_COPY_AND_ASSIGN(StartupContext); DISALLOW_COPY_AND_ASSIGN(StartupContext);
}; };
......
...@@ -9,15 +9,20 @@ ...@@ -9,15 +9,20 @@
#include <string> #include <string>
#include <utility> #include <utility>
#include "base/logging.h"
namespace cr_fuchsia { namespace cr_fuchsia {
FakeComponentContext::FakeComponentContext( FakeComponentContext::FakeComponentContext(
AgentImpl::CreateComponentStateCallback create_component_state_callback, AgentImpl::CreateComponentStateCallback create_component_state_callback,
base::fuchsia::ServiceDirectory* service_directory, base::fuchsia::ServiceDirectory* service_directory,
std::string component_url) base::StringPiece component_url)
: agent_impl_(service_directory, : binding_(service_directory, this),
// Publishing the Agent to |service_directory| is not necessary, but
// also shouldn't do any harm.
agent_impl_(service_directory,
std::move(create_component_state_callback)), std::move(create_component_state_callback)),
component_url_(component_url) {} component_url_(component_url.as_string()) {}
void FakeComponentContext::ConnectToAgent( void FakeComponentContext::ConnectToAgent(
std::string agent_url, std::string agent_url,
...@@ -26,6 +31,10 @@ void FakeComponentContext::ConnectToAgent( ...@@ -26,6 +31,10 @@ void FakeComponentContext::ConnectToAgent(
agent_impl_.Connect(component_url_, std::move(services)); agent_impl_.Connect(component_url_, std::move(services));
} }
void FakeComponentContext::NotImplemented_(const std::string& name) {
NOTIMPLEMENTED() << " API: " << name;
}
FakeComponentContext::~FakeComponentContext() = default; FakeComponentContext::~FakeComponentContext() = default;
} // namespace cr_fuchsia } // namespace cr_fuchsia
...@@ -11,6 +11,8 @@ ...@@ -11,6 +11,8 @@
#include <string> #include <string>
#include <utility> #include <utility>
#include "base/strings/string_piece.h"
namespace cr_fuchsia { namespace cr_fuchsia {
// Used to test interactions with an Agent in unit-tests for a component. // Used to test interactions with an Agent in unit-tests for a component.
...@@ -26,17 +28,20 @@ class FakeComponentContext ...@@ -26,17 +28,20 @@ class FakeComponentContext
explicit FakeComponentContext( explicit FakeComponentContext(
AgentImpl::CreateComponentStateCallback create_component_state_callback, AgentImpl::CreateComponentStateCallback create_component_state_callback,
base::fuchsia::ServiceDirectory* service_directory, base::fuchsia::ServiceDirectory* service_directory,
std::string component_url); base::StringPiece component_url);
~FakeComponentContext() override; ~FakeComponentContext() override;
// fuchsia::modular::ComponentContext implementation. // fuchsia::modular::ComponentContext_TestBase implementation.
void ConnectToAgent( void ConnectToAgent(
std::string agent_url, std::string agent_url,
fidl::InterfaceRequest<::fuchsia::sys::ServiceProvider> services, fidl::InterfaceRequest<::fuchsia::sys::ServiceProvider> services,
fidl::InterfaceRequest<fuchsia::modular::AgentController> controller) fidl::InterfaceRequest<fuchsia::modular::AgentController> controller)
override; override;
void NotImplemented_(const std::string& name) override;
private: private:
base::fuchsia::ScopedServiceBinding<fuchsia::modular::ComponentContext>
binding_;
AgentImpl agent_impl_; AgentImpl agent_impl_;
const std::string component_url_; const std::string component_url_;
......
...@@ -53,6 +53,7 @@ source_set("cast_runner_core") { ...@@ -53,6 +53,7 @@ source_set("cast_runner_core") {
"//base", "//base",
"//fuchsia:web_fidl", "//fuchsia:web_fidl",
"//fuchsia/base", "//fuchsia/base",
"//third_party/fuchsia-sdk/sdk:modular",
"//url", "//url",
] ]
public_deps = [ public_deps = [
......
...@@ -36,7 +36,7 @@ CastChannelBindings::CastChannelBindings( ...@@ -36,7 +36,7 @@ CastChannelBindings::CastChannelBindings(
DCHECK(frame_); DCHECK(frame_);
channel_consumer_.set_error_handler([this](zx_status_t status) mutable { channel_consumer_.set_error_handler([this](zx_status_t status) mutable {
ZX_LOG(ERROR, status) << " Agent disconnected."; ZX_LOG(ERROR, status) << " Agent disconnected";
std::move(on_error_closure_).Run(); std::move(on_error_closure_).Run();
}); });
......
...@@ -16,6 +16,8 @@ ...@@ -16,6 +16,8 @@
namespace { namespace {
constexpr int kBindingsFailureExitCode = 129; constexpr int kBindingsFailureExitCode = 129;
const char kCastAgentPackageUrl[] =
"fuchsia-pkg://fuchsia.com/cast_agent#meta/cast_agent.cmx";
} // namespace } // namespace
CastComponent::CastComponent( CastComponent::CastComponent(
...@@ -31,11 +33,23 @@ CastComponent::CastComponent( ...@@ -31,11 +33,23 @@ CastComponent::CastComponent(
navigation_observer_binding_(this) { navigation_observer_binding_(this) {
base::AutoReset<bool> constructor_active_reset(&constructor_active_, true); base::AutoReset<bool> constructor_active_reset(&constructor_active_, true);
// Fetch the ComponentContext for this instance.
fuchsia::modular::ComponentContextPtr component_context;
startup_context()->incoming_services()->ConnectToService(
component_context.NewRequest());
// Request to connect to the Cast agent.
component_context->ConnectToAgent(kCastAgentPackageUrl,
agent_services_.NewRequest(),
agent_controller_.NewRequest());
// Bind to the CastChannel service provided by the Agent.
chromium::cast::CastChannelPtr cast_channel_ptr;
agent_services_->ConnectToService(
chromium::cast::CastChannel::Name_,
cast_channel_ptr.NewRequest().TakeChannel());
cast_channel_ = std::make_unique<CastChannelBindings>( cast_channel_ = std::make_unique<CastChannelBindings>(
frame(), &connector_, frame(), &connector_, std::move(cast_channel_ptr),
startup_context()
->incoming_services()
->ConnectToService<chromium::cast::CastChannel>(),
base::BindOnce(&CastComponent::DestroyComponent, base::Unretained(this), base::BindOnce(&CastComponent::DestroyComponent, base::Unretained(this),
kBindingsFailureExitCode, kBindingsFailureExitCode,
fuchsia::sys::TerminationReason::INTERNAL_ERROR)); fuchsia::sys::TerminationReason::INTERNAL_ERROR));
......
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
#ifndef FUCHSIA_RUNNERS_CAST_CAST_COMPONENT_H_ #ifndef FUCHSIA_RUNNERS_CAST_CAST_COMPONENT_H_
#define FUCHSIA_RUNNERS_CAST_CAST_COMPONENT_H_ #define FUCHSIA_RUNNERS_CAST_CAST_COMPONENT_H_
#include <fuchsia/modular/cpp/fidl.h>
#include <fuchsia/sys/cpp/fidl.h>
#include <lib/fidl/cpp/binding.h> #include <lib/fidl/cpp/binding.h>
#include <memory> #include <memory>
...@@ -43,6 +45,9 @@ class CastComponent : public WebComponent, ...@@ -43,6 +45,9 @@ class CastComponent : public WebComponent,
std::unique_ptr<CastChannelBindings> cast_channel_; std::unique_ptr<CastChannelBindings> cast_channel_;
QueryableDataBindings queryable_data_; QueryableDataBindings queryable_data_;
fuchsia::sys::ServiceProviderPtr agent_services_;
fuchsia::modular::AgentControllerPtr agent_controller_;
fidl::Binding<chromium::web::NavigationEventObserver> fidl::Binding<chromium::web::NavigationEventObserver>
navigation_observer_binding_; navigation_observer_binding_;
......
...@@ -13,6 +13,8 @@ ...@@ -13,6 +13,8 @@
#include "base/strings/stringprintf.h" #include "base/strings/stringprintf.h"
#include "base/test/bind_test_util.h" #include "base/test/bind_test_util.h"
#include "base/test/test_timeouts.h" #include "base/test/test_timeouts.h"
#include "fuchsia/base/agent_impl.h"
#include "fuchsia/base/fake_component_context.h"
#include "fuchsia/base/fit_adapter.h" #include "fuchsia/base/fit_adapter.h"
#include "fuchsia/base/result_receiver.h" #include "fuchsia/base/result_receiver.h"
#include "fuchsia/engine/test/test_common.h" #include "fuchsia/engine/test/test_common.h"
...@@ -38,37 +40,62 @@ void ComponentErrorHandler(zx_status_t status) { ...@@ -38,37 +40,62 @@ void ComponentErrorHandler(zx_status_t status) {
class FakeCastChannel : public chromium::cast::CastChannel { class FakeCastChannel : public chromium::cast::CastChannel {
public: public:
FakeCastChannel() = default; explicit FakeCastChannel(base::fuchsia::ServiceDirectory* directory)
: binding_(directory, this) {}
// Returns null if the Cast channel is not open.
const chromium::web::MessagePortPtr& port() const { return port_; }
void set_on_opened(base::OnceClosure on_opened) {
on_opened_ = std::move(on_opened);
}
protected:
// chromium::web::CastChannel implementation. // chromium::web::CastChannel implementation.
void OnOpened(fidl::InterfaceHandle<chromium::web::MessagePort> channel, void OnOpened(fidl::InterfaceHandle<chromium::web::MessagePort> channel,
OnOpenedCallback callback_ignored) override { OnOpenedCallback callback_ignored) override {
// |callback_ignored| is dropped because these tests don't exercise multiple port_ = channel.Bind();
// channel lifetimes.
connected_channel_ = channel.Bind(); if (on_opened_)
std::move(on_opened_).Run();
if (on_channel_connected_) callback_ignored();
std::move(on_channel_connected_).Run();
} }
chromium::web::MessagePort* connected_channel() const { const base::fuchsia::ScopedServiceBinding<chromium::cast::CastChannel>
// Return nullptr if |connected_channel_| is not currently bound. binding_;
return connected_channel_ ? connected_channel_.get() : nullptr;
// Null until the Cast app connects to the Cast channel.
chromium::web::MessagePortPtr port_;
// Invoked when the contect opens a new Cast channel, if set.
base::OnceClosure on_opened_;
DISALLOW_COPY_AND_ASSIGN(FakeCastChannel);
};
class FakeComponentState : public cr_fuchsia::AgentImpl::ComponentStateBase {
public:
explicit FakeComponentState(base::StringPiece component_url)
: ComponentStateBase(component_url),
cast_channel_(std::make_unique<FakeCastChannel>(service_directory())) {}
~FakeComponentState() override {
if (on_delete_)
std::move(on_delete_).Run();
} }
void set_on_channel_connected(base::OnceClosure on_channel_connected) { void set_on_delete(base::OnceClosure on_delete) {
on_channel_connected_ = std::move(on_channel_connected); on_delete_ = std::move(on_delete);
} }
protected: FakeCastChannel* cast_channel() { return cast_channel_.get(); }
// The connected Cast Channel. void ClearCastChannel() { cast_channel_.reset(); }
chromium::web::MessagePortPtr connected_channel_;
// A pending on-connect callback, to be invoked once a Cast Channel is protected:
// received. std::unique_ptr<FakeCastChannel> cast_channel_;
base::OnceClosure on_channel_connected_; base::OnceClosure on_delete_;
DISALLOW_COPY_AND_ASSIGN(FakeCastChannel); DISALLOW_COPY_AND_ASSIGN(FakeComponentState);
}; };
} // namespace } // namespace
...@@ -120,27 +147,28 @@ class CastRunnerIntegrationTest : public testing::Test { ...@@ -120,27 +147,28 @@ class CastRunnerIntegrationTest : public testing::Test {
} }
void WaitUntilCastChannelOpened() { void WaitUntilCastChannelOpened() {
if (cast_channel_.connected_channel()) if (component_state_->cast_channel()->port())
return; return;
base::RunLoop run_loop; base::RunLoop run_loop;
cast_channel_.set_on_channel_connected(run_loop.QuitClosure()); component_state_->cast_channel()->set_on_opened(run_loop.QuitClosure());
run_loop.Run(); run_loop.Run();
DCHECK(cast_channel_.connected_channel()); DCHECK(component_state_->cast_channel()->port());
} }
fuchsia::sys::ComponentControllerPtr StartCastComponent( fuchsia::sys::ComponentControllerPtr StartCastComponent(
base::StringPiece component_url) { base::StringPiece component_url) {
DCHECK(!component_services_); DCHECK(!component_state_);
// Create a ServiceDirectory and publish the CastChannel into it. // Create a ServiceDirectory and publish the ComponentContext into it.
fidl::InterfaceHandle<fuchsia::io::Directory> directory; fidl::InterfaceHandle<fuchsia::io::Directory> directory;
component_services_ = std::make_unique<base::fuchsia::ServiceDirectory>( component_services_ = std::make_unique<base::fuchsia::ServiceDirectory>(
directory.NewRequest()); directory.NewRequest());
cast_channel_binding_ = std::make_unique< component_context_ = std::make_unique<cr_fuchsia::FakeComponentContext>(
base::fuchsia::ScopedServiceBinding<chromium::cast::CastChannel>>( base::BindRepeating(&CastRunnerIntegrationTest::OnComponentConnect,
component_services_.get(), &cast_channel_); base::Unretained(this)),
component_services_.get(), component_url);
// Configure the Runner, including a service directory channel to publish // Configure the Runner, including a service directory channel to publish
// services to. // services to.
...@@ -165,6 +193,13 @@ class CastRunnerIntegrationTest : public testing::Test { ...@@ -165,6 +193,13 @@ class CastRunnerIntegrationTest : public testing::Test {
} }
protected: protected:
std::unique_ptr<cr_fuchsia::AgentImpl::ComponentStateBase> OnComponentConnect(
base::StringPiece component_url) {
auto component_state = std::make_unique<FakeComponentState>(component_url);
component_state_ = component_state.get();
return component_state;
}
const base::RunLoop::ScopedRunTimeoutForTest run_timeout_; const base::RunLoop::ScopedRunTimeoutForTest run_timeout_;
base::MessageLoopForIO message_loop_; base::MessageLoopForIO message_loop_;
net::EmbeddedTestServer test_server_; net::EmbeddedTestServer test_server_;
...@@ -173,12 +208,10 @@ class CastRunnerIntegrationTest : public testing::Test { ...@@ -173,12 +208,10 @@ class CastRunnerIntegrationTest : public testing::Test {
FakeApplicationConfigManager app_config_manager_; FakeApplicationConfigManager app_config_manager_;
fidl::Binding<chromium::cast::ApplicationConfigManager> app_config_binding_; fidl::Binding<chromium::cast::ApplicationConfigManager> app_config_binding_;
// Incoming service directory, CastChannel and service bindings. // Incoming service directory, ComponentContext and per-component state.
std::unique_ptr<base::fuchsia::ServiceDirectory> component_services_; std::unique_ptr<base::fuchsia::ServiceDirectory> component_services_;
FakeCastChannel cast_channel_; std::unique_ptr<cr_fuchsia::FakeComponentContext> component_context_;
std::unique_ptr< FakeComponentState* component_state_ = nullptr;
base::fuchsia::ScopedServiceBinding<chromium::cast::CastChannel>>
cast_channel_binding_;
// ServiceDirectory into which the CastRunner will publish itself. // ServiceDirectory into which the CastRunner will publish itself.
std::unique_ptr<base::fuchsia::ServiceDirectory> public_services_; std::unique_ptr<base::fuchsia::ServiceDirectory> public_services_;
...@@ -230,18 +263,18 @@ TEST_F(CastRunnerIntegrationTest, BasicRequest) { ...@@ -230,18 +263,18 @@ TEST_F(CastRunnerIntegrationTest, BasicRequest) {
} }
// Verify that the component is torn down when |component_controller| is // Verify that the component is torn down when |component_controller| is
// unbound, by observing the destruction of its child Interfaces. // unbound.
base::RunLoop destruction_run_loop; base::RunLoop run_loop;
nav_controller.set_error_handler( component_state_->set_on_delete(run_loop.QuitClosure());
[&destruction_run_loop](zx_status_t) { destruction_run_loop.Quit(); });
component_controller.Unbind(); component_controller.Unbind();
destruction_run_loop.Run(); run_loop.Run();
} }
TEST_F(CastRunnerIntegrationTest, IncorrectCastAppId) { TEST_F(CastRunnerIntegrationTest, IncorrectCastAppId) {
// Launch the a component with an invalid Cast app Id. // Launch the a component with an invalid Cast app Id.
fuchsia::sys::ComponentControllerPtr component_controller = fuchsia::sys::ComponentControllerPtr component_controller =
StartCastComponent("cast:99999999"); StartCastComponent("cast:99999999");
component_controller.set_error_handler(&ComponentErrorHandler);
// Run the loop until the ComponentController is dropped, or a WebComponent is // Run the loop until the ComponentController is dropped, or a WebComponent is
// created. // created.
...@@ -302,17 +335,17 @@ TEST_F(CastRunnerIntegrationTest, CastChannel) { ...@@ -302,17 +335,17 @@ TEST_F(CastRunnerIntegrationTest, CastChannel) {
base::RunLoop run_loop; base::RunLoop run_loop;
cr_fuchsia::ResultReceiver<chromium::web::WebMessage> message( cr_fuchsia::ResultReceiver<chromium::web::WebMessage> message(
run_loop.QuitClosure()); run_loop.QuitClosure());
cast_channel_.connected_channel()->ReceiveMessage( component_state_->cast_channel()->port()->ReceiveMessage(
cr_fuchsia::CallbackToFitFunction(message.GetReceiveCallback())); cr_fuchsia::CallbackToFitFunction(message.GetReceiveCallback()));
run_loop.Run(); run_loop.Run();
EXPECT_EQ(cr_fuchsia::StringFromMemBufferOrDie(message->data), expected); EXPECT_EQ(cr_fuchsia::StringFromMemBufferOrDie(message->data), expected);
} }
// Shutdown the component and wait for the CastChannel to close. // Shutdown the component and wait for the teardown of its state.
component_controller.Unbind();
base::RunLoop run_loop; base::RunLoop run_loop;
cast_channel_binding_->SetOnLastClientCallback(run_loop.QuitClosure()); component_state_->set_on_delete(run_loop.QuitClosure());
component_controller.Unbind();
run_loop.Run(); run_loop.Run();
} }
...@@ -326,15 +359,25 @@ TEST_F(CastRunnerIntegrationTest, CastChannelConsumerDropped) { ...@@ -326,15 +359,25 @@ TEST_F(CastRunnerIntegrationTest, CastChannelConsumerDropped) {
fuchsia::sys::ComponentControllerPtr component_controller = fuchsia::sys::ComponentControllerPtr component_controller =
StartCastComponent(base::StringPrintf("cast:%s", kCastChannelAppId)); StartCastComponent(base::StringPrintf("cast:%s", kCastChannelAppId));
// Expect that disconnecting the Cast Channel consumer service will trigger // Spin the message loop to handle creation of the component state.
// the destruction of the Cast Component. base::RunLoop().RunUntilIdle();
cast_channel_binding_.reset(); ASSERT_TRUE(component_state_);
// Disconnecting the CastChannel should trigger the component to teardown,
// resulting in our ComponentControllerPtr being dropped, and the component
// state held by the agent being deleted.
component_state_->set_on_delete(base::MakeExpectedRunClosure(FROM_HERE));
component_state_->ClearCastChannel();
base::RunLoop run_loop; base::RunLoop run_loop;
component_controller.set_error_handler( component_controller.set_error_handler([&run_loop](zx_status_t status) {
[&run_loop](zx_status_t) { run_loop.Quit(); }); EXPECT_EQ(status, ZX_ERR_PEER_CLOSED);
run_loop.Quit();
});
run_loop.Run(); run_loop.Run();
EXPECT_FALSE(component_controller.is_bound()); EXPECT_FALSE(component_controller.is_bound());
// Give the fake agent an opportunity to perform teardown cleanup.
base::RunLoop().RunUntilIdle();
} }
TEST_F(CastRunnerIntegrationTest, CastChannelComponentControllerDropped) { TEST_F(CastRunnerIntegrationTest, CastChannelComponentControllerDropped) {
...@@ -347,12 +390,15 @@ TEST_F(CastRunnerIntegrationTest, CastChannelComponentControllerDropped) { ...@@ -347,12 +390,15 @@ TEST_F(CastRunnerIntegrationTest, CastChannelComponentControllerDropped) {
fuchsia::sys::ComponentControllerPtr component_controller = fuchsia::sys::ComponentControllerPtr component_controller =
StartCastComponent(base::StringPrintf("cast:%s", kCastChannelAppId)); StartCastComponent(base::StringPrintf("cast:%s", kCastChannelAppId));
// Expect that disconnecting the ComponentController will kill the Cast // Spin the message loop to handle creation of the component state.
// Component, which we verify indirectly by listening for the disconnection base::RunLoop().RunUntilIdle();
// of one of its CastChannel FIDL client. ASSERT_TRUE(component_state_);
component_controller.Unbind();
// Expect that disconnecting the ComponentController will destroy the Cast
// component.
base::RunLoop run_loop; base::RunLoop run_loop;
cast_channel_binding_->SetOnLastClientCallback(run_loop.QuitClosure()); component_state_->set_on_delete(run_loop.QuitClosure());
component_controller.Unbind();
run_loop.Run(); run_loop.Run();
} }
......
...@@ -49,7 +49,7 @@ WebComponent::WebComponent( ...@@ -49,7 +49,7 @@ WebComponent::WebComponent(
controller_binding_.Bind(std::move(controller_request)); controller_binding_.Bind(std::move(controller_request));
controller_binding_.set_error_handler([this](zx_status_t status) { controller_binding_.set_error_handler([this](zx_status_t status) {
ZX_LOG_IF(ERROR, status != ZX_ERR_PEER_CLOSED, status) ZX_LOG_IF(ERROR, status != ZX_ERR_PEER_CLOSED, status)
<< " ComponentController disconnected."; << " ComponentController disconnected";
// Teardown the component with dummy values, since ComponentController // Teardown the component with dummy values, since ComponentController
// channel isn't there to receive them. // channel isn't there to receive them.
DestroyComponent(0, fuchsia::sys::TerminationReason::EXITED); DestroyComponent(0, fuchsia::sys::TerminationReason::EXITED);
......
...@@ -94,7 +94,6 @@ void WebContentRunner::GetWebComponentForTest( ...@@ -94,7 +94,6 @@ void WebContentRunner::GetWebComponentForTest(
} }
void WebContentRunner::DestroyComponent(WebComponent* component) { void WebContentRunner::DestroyComponent(WebComponent* component) {
LOG(ERROR) << "DestroyComponent " << components_.size();
components_.erase(components_.find(component)); components_.erase(components_.find(component));
if (components_.empty()) if (components_.empty())
......
...@@ -61,6 +61,8 @@ class WebRunnerSmokeTest : public testing::Test { ...@@ -61,6 +61,8 @@ class WebRunnerSmokeTest : public testing::Test {
net::EmbeddedTestServer test_server_; net::EmbeddedTestServer test_server_;
base::RunLoop run_loop_; base::RunLoop run_loop_;
DISALLOW_COPY_AND_ASSIGN(WebRunnerSmokeTest);
}; };
TEST_F(WebRunnerSmokeTest, RequestHtmlAndImage) { TEST_F(WebRunnerSmokeTest, RequestHtmlAndImage) {
......
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