| // Copyright 2017 The Fuchsia 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 "peridot/bin/sessionmgr/entity_provider_runner/entity_provider_controller.h" |
| |
| #include <lib/fxl/logging.h> |
| |
| #include "peridot/bin/sessionmgr/entity_provider_runner/entity_provider_runner.h" |
| |
| namespace modular { |
| |
| class EntityProviderController::EntityImpl : fuchsia::modular::Entity { |
| public: |
| EntityImpl(EntityProviderController* const entity_provider_controller, |
| fuchsia::modular::EntityProvider* const entity_provider, |
| const std::string& cookie, const std::string& entity_reference) |
| : entity_provider_controller_(entity_provider_controller), |
| entity_provider_(entity_provider), |
| cookie_(cookie), |
| entity_reference_(entity_reference) { |
| entity_bindings_.set_empty_set_handler([this] { |
| entity_provider_controller_->OnEmptyEntityImpls(cookie_); |
| // |this| is no longer valid. |
| }); |
| } |
| |
| // Serves this |fuchsia::modular::Entity| for the cookie this |EntityImpl| was |
| // instantiated for. |
| void ProvideEntity(fidl::InterfaceRequest<fuchsia::modular::Entity> request) { |
| entity_bindings_.AddBinding(this, std::move(request)); |
| } |
| |
| private: |
| // |fuchsia::modular::Entity| |
| void GetTypes(GetTypesCallback callback) override { |
| entity_provider_->GetTypes(cookie_, callback); |
| } |
| |
| // |fuchsia::modular::Entity| |
| void GetData(fidl::StringPtr type, GetDataCallback callback) override { |
| entity_provider_->GetData(cookie_, type, callback); |
| } |
| |
| // |fuchsia::modular::Entity| |
| void WriteData(fidl::StringPtr type, fuchsia::mem::Buffer data, |
| WriteDataCallback callback) override { |
| entity_provider_->WriteData(cookie_, type, std::move(data), callback); |
| } |
| |
| // |fuchsia::modular::Entity| |
| void GetReference(GetReferenceCallback callback) override { |
| callback(entity_reference_); |
| } |
| |
| // |fuchsia::modular::Entity| |
| void Watch( |
| fidl::StringPtr type, |
| fidl::InterfaceHandle<fuchsia::modular::EntityWatcher> watcher) override { |
| entity_provider_->Watch(cookie_, type, std::move(watcher)); |
| } |
| |
| EntityProviderController* const entity_provider_controller_; |
| fuchsia::modular::EntityProvider* const entity_provider_; |
| const std::string cookie_; |
| const std::string entity_reference_; |
| fidl::BindingSet<fuchsia::modular::Entity> entity_bindings_; |
| |
| FXL_DISALLOW_COPY_AND_ASSIGN(EntityImpl); |
| }; |
| |
| EntityProviderController::EntityProviderController( |
| fuchsia::modular::EntityProviderPtr entity_provider, |
| fuchsia::modular::AgentControllerPtr agent_controller, |
| std::function<void()> done) |
| : entity_provider_(std::move(entity_provider)), |
| agent_controller_(std::move(agent_controller)), |
| done_(done) { |
| FXL_DLOG(INFO) << "Running fuchsia::modular::EntityProvider"; |
| if (agent_controller_) { |
| agent_controller_.set_error_handler([this](zx_status_t status) { |
| done_(); |
| // |this| no longer valid. |
| }); |
| } |
| } |
| |
| EntityProviderController::~EntityProviderController() = default; |
| |
| void EntityProviderController::ProvideEntity( |
| const std::string& cookie, const std::string& entity_reference, |
| fidl::InterfaceRequest<fuchsia::modular::Entity> request) { |
| auto it = entity_impls_.find(cookie); |
| if (it == entity_impls_.end()) { |
| bool inserted; |
| std::tie(it, inserted) = entity_impls_.insert(std::make_pair( |
| cookie, std::make_unique<EntityImpl>(this, entity_provider_.get(), |
| cookie, entity_reference))); |
| FXL_DCHECK(inserted); |
| } |
| // When there are no more |fuchsia::modular::Entity|s being serviced for this |
| // |cookie|, |OnEmptyEntityImpl()| is triggered. |
| it->second->ProvideEntity(std::move(request)); |
| } |
| |
| void EntityProviderController::OnEmptyEntityImpls(const std::string cookie) { |
| entity_impls_.erase(cookie); |
| if (entity_impls_.size() == 0ul) { |
| // We can drop our connection to the fuchsia::modular::EntityProvider at |
| // this point. |
| done_(); |
| // |this| no longer valid. |
| } |
| } |
| |
| } // namespace modular |