| // 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_ |