text: // 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 SRC_MODULAR_BIN_SESSIONMGR_STARTUP_AGENT_LAUNCHER_H_
  #define SRC_MODULAR_BIN_SESSIONMGR_STARTUP_AGENT_LAUNCHER_H_
  
  #include <fuchsia/element/cpp/fidl.h>
  #include <fuchsia/intl/cpp/fidl.h>
  #include <fuchsia/modular/cpp/fidl.h>
  #include <lib/fidl/cpp/binding_set.h>
  #include <lib/svc/cpp/service_namespace.h>
  #include <lib/svc/cpp/services.h>
  #include <lib/sys/cpp/component_context.h>
  #include <lib/zx/channel.h>
  
  #include <deque>
  #include <string>
  #include <vector>
  
  #include "src/modular/bin/sessionmgr/agent_runner/agent_runner.h"
  #include "src/modular/bin/sessionmgr/agent_services_factory.h"
  #include "src/modular/bin/sessionmgr/rate_limited_retry.h"
  #include "src/modular/lib/modular_config/modular_config_accessor.h"
  
  namespace modular {
  
  class StartupAgentLauncher : public AgentServicesFactory {
   public:
    // |context| is not owned and must outlive this instance.
    StartupAgentLauncher(
        const ModularConfigAccessor* config_accessor,
        fidl::InterfaceRequestHandler<fuchsia::modular::PuppetMaster> puppet_master_connector,
        fidl::InterfaceRequestHandler<fuchsia::modular::SessionRestartController>
            session_restart_controller_connector,
        fidl::InterfaceRequestHandler<fuchsia::intl::PropertyProvider>
            intl_property_provider_connector,
        fidl::InterfaceRequestHandler<fuchsia::element::Manager> element_manager_connector,
        fuchsia::sys::ServiceList v2_services_for_sessionmgr,
        fit::function<bool()> is_terminating_cb);
  
    ~StartupAgentLauncher() override = default;
  
    void StartAgents(AgentRunner* agent_runner, std::vector<std::string> session_agents,
                     std::vector<std::string> startup_agents);
  
    // |AgentServicesFactory|
    fuchsia::sys::ServiceList GetServicesForAgent(std::string agent_url) override;
  
   private:
    struct SessionAgentData {
      struct DeferredInterfaceRequest {
        template <class Interface>
        DeferredInterfaceRequest(fidl::InterfaceRequest<Interface> request);
  
        const char* name;
        zx::channel channel;
      };
  
      SessionAgentData();
  
      template <class Interface>
      void ConnectOrQueueServiceRequest(fidl::InterfaceRequest<Interface> request);
  
      // Used to track the lifecycle of the agent and learn if it terminates.
      fuchsia::modular::AgentControllerPtr controller;
  
      fuchsia::sys::ServiceProviderPtr services;
      // If an agent crashes, there is a period (~1 sec) where its |services|
      // interface is invalid before its controller is closed. During that
      // period, we should queue requests until we've restarted the agent.
      std::vector<DeferredInterfaceRequest> pending_service_requests;
  
      modular::RateLimitedRetry restart;
    };
  
    using ServiceProviderInitializer =
        fit::function<void(const std::string& url, component::ServiceNamespace* service_namespace)>;
    // A ServiceProviderInitializer that adds standard agent services, including
    // attributed context entry point. Returns the names
    // of the services added.
    std::vector<std::string> AddAgentServices(const std::string& url,
                                              component::ServiceNamespace* service_namespace);
  
    void StartAgent(AgentRunner* agent_runner, const std::string& url);
  
    void StartSessionAgent(AgentRunner* agent_runner, const std::string& url);
  
    std::map<std::string, SessionAgentData> session_agents_;
  
    fidl::InterfacePtr<fuchsia::modular::ComponentContext> component_context_;
    fidl::InterfacePtr<fuchsia::modular::StoryProvider> story_provider_;
    fidl::InterfacePtr<fuchsia::intl::PropertyProvider> property_provider_;
  
    const ModularConfigAccessor* config_accessor_;
    fit::function<void(fidl::InterfaceRequest<fuchsia::modular::PuppetMaster>)>
        puppet_master_connector_;
    fit::function<void(fidl::InterfaceRequest<fuchsia::modular::SessionRestartController>)>
        session_restart_controller_connector_;
    fit::function<void(fidl::InterfaceRequest<fuchsia::intl::PropertyProvider>)>
        intl_property_provider_connector_;
    fit::function<void(fidl::InterfaceRequest<fuchsia::element::Manager>)> element_manager_connector_;
  
    fuchsia::sys::ServiceList v2_services_for_sessionmgr_;
    sys::ServiceDirectory v2_services_for_sessionmgr_directory_;
  
    // Return |true| to avoid automatically restarting session_agents_.
    fit::function<bool()> is_terminating_cb_ = nullptr;
  
    // ServiceNamespace(s) backing the services provided to these agents via its
    // namespace.
    std::deque<component::ServiceNamespace> agent_namespaces_;
  };
  
  }  // namespace modular
  
  #endif  // SRC_MODULAR_BIN_SESSIONMGR_STARTUP_AGENT_LAUNCHER_H_
  