blob: 1e10e7739c799a2aa108ebe83a6814267a4b9110 [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 PERIDOT_LIB_FIDL_APP_CLIENT_H_
#define PERIDOT_LIB_FIDL_APP_CLIENT_H_
#include <memory>
#include <string>
#include <fuchsia/modular/cpp/fidl.h>
#include <fuchsia/sys/cpp/fidl.h>
#include <lib/fidl/cpp/binding.h>
#include <lib/fidl/cpp/interface_request.h>
#include <lib/fxl/macros.h>
#include <lib/fxl/time/time_delta.h>
#include <lib/svc/cpp/services.h>
#include "peridot/lib/common/async_holder.h"
namespace modular {
// A class that holds a connection to a single service instance in an
// application instance. The service instance supports life cycle with a
// Terminate() method. When calling Terminate(), the service is supposed to
// close its connection, and when that happens, we can kill the application, or
// it's gone already anyway. If the service connection doesn't close after a
// timeout, we close it and kill the application anyway.
//
// When starting an application instance, the directory pointed to by
// |data_origin| will be mapped into /data for the newly started application.
// If left empty, it'll be mapped to the root /data.
//
// |additional_services| will allow us to add custom services to an applications
// namespace.
//
// AppClientBase are the non-template parts factored out so they don't need to
// be inline. It can be used on its own too.
class AppClientBase : public AsyncHolderBase {
public:
AppClientBase(fuchsia::sys::Launcher* launcher,
fuchsia::modular::AppConfig config,
std::string data_origin = "",
fuchsia::sys::ServiceListPtr additional_services = nullptr);
~AppClientBase() override;
// Gives access to the services of the started application. Services
// obtained from it are not involved in life cycle management provided by
// AppClient, however. This is used for example to obtain the ViewProvider.
component::Services& services() { return services_; }
// Registers a handler to receive a notification when this application
// connection encounters an error. This typically happens when this
// application stops or crashes. |error_handler| will be deregistered when
// attempting graceful termination via |AsyncHolderBase::Teardown()|.
void SetAppErrorHandler(const std::function<void()>& error_handler);
private:
// The termination sequence as prescribed by AsyncHolderBase.
void ImplTeardown(std::function<void()> done) override;
void ImplReset() override;
// Service specific parts of the termination sequence.
virtual void ServiceTerminate(const std::function<void()>& done);
virtual void ServiceUnbind();
fuchsia::sys::ComponentControllerPtr app_;
component::Services services_;
FXL_DISALLOW_COPY_AND_ASSIGN(AppClientBase);
};
// A generic client that does the standard termination sequence. For a service
// with another termination sequence, another implementation could be created.
template <class Service>
class AppClient : public AppClientBase {
public:
AppClient(fuchsia::sys::Launcher* const launcher,
fuchsia::modular::AppConfig config, std::string data_origin = "",
fuchsia::sys::ServiceListPtr additional_services = nullptr)
: AppClientBase(launcher, std::move(config), std::move(data_origin),
std::move(additional_services)) {
services().ConnectToService(service_.NewRequest());
}
~AppClient() override = default;
fidl::InterfacePtr<Service>& primary_service() { return service_; }
private:
void ServiceTerminate(const std::function<void()>& done) override {
// The service is expected to acknowledge the Terminate() request by
// closing its connection within the timeout set in Teardown().
service_.set_error_handler([done](zx_status_t status) { done(); });
service_->Terminate();
}
void ServiceUnbind() override { service_.Unbind(); }
fidl::InterfacePtr<Service> service_;
FXL_DISALLOW_COPY_AND_ASSIGN(AppClient);
};
template <>
void AppClient<fuchsia::modular::Lifecycle>::ServiceTerminate(
const std::function<void()>& done);
} // namespace modular
#endif // PERIDOT_LIB_FIDL_APP_CLIENT_H_