blob: f7f2a8f39518147fc27e581b73ca5d86c1e075f1 [file] [log] [blame]
// 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.
#ifndef LIB_APP_DRIVER_CPP_AGENT_DRIVER_H_
#define LIB_APP_DRIVER_CPP_AGENT_DRIVER_H_
#include <memory>
#include <fuchsia/modular/cpp/fidl.h>
#include <fuchsia/sys/cpp/fidl.h>
#include <lib/agent/cpp/agent_impl.h>
#include <lib/async/cpp/task.h>
#include <lib/async/default.h>
#include <lib/component/cpp/startup_context.h>
#include <lib/fidl/cpp/binding.h>
#include <lib/fidl/cpp/interface_request.h>
#include <src/lib/fxl/logging.h>
#include <lib/lifecycle/cpp/lifecycle_impl.h>
namespace modular {
// This interface is passed to the Impl object that AgentDriver initializes.
class AgentHost {
public:
virtual component::StartupContext* startup_context() = 0;
virtual fuchsia::modular::AgentContext* agent_context() = 0;
};
// AgentDriver provides a way to write agents and participate in application
// lifecycle.
//
// class HelloAgent {
// public:
// HelloAgent(AgentHost* host) {}
//
// // Called by AgentDriver.
// void Connect(fidl::InterfaceRequest<ServiceProvider> outgoing_services) {}
//
// // Called by AgentDriver.
// void RunTask(const fidl::StringPtr& task_id,
// fit::function<void()> done) { done(); }
//
// // Called by AgentDriver.
// void Terminate(fit::function<void()> done) { done(); }
// };
//
// int main(int argc, const char** argv) {
// async::Loop loop(&kAsyncLoopConfigAttachToThread);
// auto context = component::StartupContext::CreateFromStartupInfo();
// modular::AgentDriver<HelloAgent> driver(context.get(),
// [&loop] { loop.Quit(); });
// loop.Run();
// return 0;
// }
template <typename Impl>
class AgentDriver : LifecycleImpl::Delegate, AgentImpl::Delegate, AgentHost {
public:
AgentDriver(component::StartupContext* const context,
fit::function<void()> on_terminated)
: context_(context),
lifecycle_impl_(context->outgoing().deprecated_services(), this),
agent_impl_(std::make_unique<AgentImpl>(
context->outgoing().deprecated_services(),
static_cast<AgentImpl::Delegate*>(this))),
on_terminated_(std::move(on_terminated)),
agent_context_(context_->ConnectToEnvironmentService<
fuchsia::modular::AgentContext>()),
impl_(std::make_unique<Impl>(static_cast<AgentHost*>(this))) {}
virtual ~AgentDriver() = default;
private:
// |AgentHost|
component::StartupContext* startup_context() override { return context_; }
// |AgentHost|
fuchsia::modular::AgentContext* agent_context() override {
FXL_DCHECK(agent_context_);
return agent_context_.get();
}
// |AgentImpl::Delegate|
void Connect(fidl::InterfaceRequest<fuchsia::sys::ServiceProvider>
outgoing_services_request) override {
impl_->Connect(std::move(outgoing_services_request));
};
// |AgentImpl::Delegate|
void RunTask(const fidl::StringPtr& task_id,
fit::function<void()> done) override {
impl_->RunTask(task_id, std::move(done));
};
// |LifecycleImpl::Delegate|
void Terminate() override {
agent_impl_.reset();
if (impl_) {
impl_->Terminate([this] {
// Cf. AppDriver::Terminate().
async::PostTask(async_get_default_dispatcher(), [this] {
impl_.reset();
on_terminated_();
});
});
} else {
on_terminated_();
}
}
component::StartupContext* const context_;
LifecycleImpl lifecycle_impl_;
std::unique_ptr<AgentImpl> agent_impl_;
fit::function<void()> on_terminated_;
fuchsia::modular::AgentContextPtr agent_context_;
std::unique_ptr<Impl> impl_;
FXL_DISALLOW_COPY_AND_ASSIGN(AgentDriver);
};
} // namespace modular
#endif // LIB_APP_DRIVER_CPP_AGENT_DRIVER_H_