blob: 154cbbfddb632f55bf582edb87d99653234ec2d2 [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 "lib/agent/cpp/agent_impl.h"
#include "lib/agent/fidl/agent.fidl.h"
#include "lib/agent/fidl/agent_context.fidl.h"
#include "lib/app/cpp/application_context.h"
#include "lib/app/fidl/service_provider.fidl.h"
#include "lib/fidl/cpp/bindings/binding.h"
#include "lib/fidl/cpp/bindings/interface_request.h"
#include "lib/fsl/tasks/message_loop.h"
#include "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 app::ApplicationContext* application_context() = 0;
virtual 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::String& task_id,
// const std::function<void()>& done) { done(); }
//
// // Called by AgentDriver.
// void Terminate(const std::function<void()>& done) { done(); }
// };
//
// int main(int argc, const char** argv) {
// fsl::MessageLoop loop;
// auto app_context = app::ApplicationContext::CreateFromStartupInfo();
// modular::AgentDriver<HelloAgent> driver(app_context.get(),
// [&loop] { loop.QuitNow(); });
// loop.Run();
// return 0;
// }
template <typename Impl>
class AgentDriver : LifecycleImpl::Delegate, AgentImpl::Delegate, AgentHost {
public:
AgentDriver(app::ApplicationContext* const app_context,
std::function<void()> on_terminated)
: app_context_(app_context),
lifecycle_impl_(app_context->outgoing_services(), this),
agent_impl_(std::make_unique<AgentImpl>(
app_context->outgoing_services(),
static_cast<AgentImpl::Delegate*>(this))),
on_terminated_(std::move(on_terminated)) {}
private:
// |AgentHost|
app::ApplicationContext* application_context() override {
return app_context_;
}
// |AgentHost|
AgentContext* agent_context() override {
FXL_DCHECK(agent_context_);
return agent_context_.get();
}
// |AgentImpl::Delegate|
void AgentInit(fidl::InterfaceHandle<AgentContext> agent_context) override {
agent_context_.Bind(std::move(agent_context));
impl_ = std::make_unique<Impl>(static_cast<AgentHost*>(this));
}
// |AgentImpl::Delegate|
void Connect(fidl::InterfaceRequest<app::ServiceProvider>
outgoing_services_request) override {
impl_->Connect(std::move(outgoing_services_request));
};
// |AgentImpl::Delegate|
void RunTask(const fidl::String& task_id,
const std::function<void()>& done) override {
impl_->RunTask(task_id, done);
};
// |LifecycleImpl::Delegate|
void Terminate() override {
agent_impl_.reset();
if (impl_) {
impl_->Terminate([this] {
// Cf. AppDriver::Terminate().
fsl::MessageLoop::GetCurrent()->task_runner()->PostTask([this] {
impl_.reset();
on_terminated_();
});
});
} else {
on_terminated_();
}
}
app::ApplicationContext* const app_context_;
LifecycleImpl lifecycle_impl_;
std::unique_ptr<AgentImpl> agent_impl_;
std::function<void()> on_terminated_;
AgentContextPtr agent_context_;
std::unique_ptr<Impl> impl_;
FXL_DISALLOW_COPY_AND_ASSIGN(AgentDriver);
};
} // namespace modular
#endif // LIB_APP_DRIVER_CPP_AGENT_DRIVER_H_