blob: b692599f2a2a218185b171a62716f32167dd87b9 [file] [log] [blame]
// Copyright 2019 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/base/agent_impl.h"
#include <lib/sys/cpp/component_context.h>
#include "base/bind.h"
#include "base/fuchsia/default_context.h"
namespace cr_fuchsia {
AgentImpl::ComponentStateBase::~ComponentStateBase() = default;
AgentImpl::ComponentStateBase::ComponentStateBase(
base::StringPiece component_id)
: component_id_(component_id) {
fidl::InterfaceHandle<::fuchsia::io::Directory> directory;
outgoing_directory_.GetOrCreateDirectory("svc")->Serve(
fuchsia::io::OPEN_RIGHT_READABLE | fuchsia::io::OPEN_RIGHT_WRITABLE,
directory.NewRequest().TakeChannel());
service_provider_ = std::make_unique<base::fuchsia::ServiceProviderImpl>(
std::move(directory));
// Tear down this instance when the client disconnects from the directory.
service_provider_->SetOnLastClientDisconnectedClosure(base::BindOnce(
&ComponentStateBase::TeardownIfUnused, base::Unretained(this)));
}
void AgentImpl::ComponentStateBase::DisconnectClientsAndTeardown() {
agent_impl_->DeleteComponentState(component_id_);
// Do not touch |this|, since it is already gone.
}
void AgentImpl::ComponentStateBase::TeardownIfUnused() {
DCHECK(agent_impl_);
// Don't teardown if the ServiceProvider has client(s).
if (service_provider_->has_clients())
return;
// Don't teardown if caller-specified bindings still have clients.
for (auto& keepalive_callback : keepalive_callbacks_) {
if (keepalive_callback.Run())
return;
}
DisconnectClientsAndTeardown();
// Do not touch |this|, since it is already gone.
}
AgentImpl::AgentImpl(
sys::OutgoingDirectory* outgoing_directory,
CreateComponentStateCallback create_component_state_callback)
: create_component_state_callback_(
std::move(create_component_state_callback)),
agent_binding_(outgoing_directory, this) {}
AgentImpl::~AgentImpl() {
DCHECK(active_components_.empty());
}
void AgentImpl::Connect(
std::string requester_url,
fidl::InterfaceRequest<::fuchsia::sys::ServiceProvider> services) {
auto it = active_components_.find(requester_url);
if (it == active_components_.end()) {
std::unique_ptr<ComponentStateBase> component_state =
create_component_state_callback_.Run(requester_url);
if (!component_state)
return;
auto result =
active_components_.emplace(requester_url, std::move(component_state));
it = result.first;
CHECK(result.second);
it->second->agent_impl_ = this;
}
it->second->service_provider_->AddBinding(std::move(services));
}
void AgentImpl::DeleteComponentState(base::StringPiece component_id) {
size_t removed_components = active_components_.erase(component_id);
DCHECK_EQ(removed_components, 1u);
}
} // namespace cr_fuchsia