text: // Copyright 2018 The Chromium OS 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 VM_TOOLS_CICERONE_SERVICE_H_
  #define VM_TOOLS_CICERONE_SERVICE_H_
  
  #include <map>
  #include <memory>
  #include <string>
  #include <utility>
  #include <vector>
  
  #include <base/callback.h>
  #include <base/files/file_descriptor_watcher_posix.h>
  #include <base/files/file_path.h>
  #include <base/files/file_path_watcher.h>
  #include <base/macros.h>
  #include <base/memory/ref_counted.h>
  #include <base/memory/weak_ptr.h>
  #include <base/optional.h>
  #include <base/sequence_checker.h>
  #include <base/threading/thread.h>
  #include <brillo/process/process.h>
  #include <dbus/bus.h>
  #include <dbus/exported_object.h>
  #include <dbus/message.h>
  #include <grpcpp/grpcpp.h>
  #include <vm_applications/proto_bindings/apps.pb.h>
  #include <vm_cicerone/proto_bindings/cicerone_service.pb.h>
  #include <vm_concierge/proto_bindings/concierge_service.pb.h>
  #include <chromeos/dbus/service_constants.h>
  
  #include "vm_tools/cicerone/container.h"
  #include "vm_tools/cicerone/container_listener_impl.h"
  #include "vm_tools/cicerone/crash_listener_impl.h"
  #include "vm_tools/cicerone/shill_client.h"
  #include "vm_tools/cicerone/tremplin_listener_impl.h"
  #include "vm_tools/cicerone/virtual_machine.h"
  
  namespace vm_tools {
  namespace cicerone {
  
  // VM Container Service responsible for responding to DBus method calls for
  // interacting with VM containers.
  class Service final {
   public:
    // Creates a new Service instance.  |quit_closure| is posted to the TaskRunner
    // for the current thread when this process receives a SIGTERM. |bus| is a
    // connection to the SYSTEM dbus.
    // Normally, services are bound to a AF_VSOCK and AF_UNIX socket. For unit
    // tests, the services only listen on an AF_UNIX socket by giving
    // |unix_socket_path_for_testing| a value.
    static std::unique_ptr<Service> Create(
        base::Closure quit_closure,
        const base::Optional<base::FilePath>& unix_socket_path_for_testing,
        scoped_refptr<dbus::Bus> bus);
  
    ~Service();
  
    ContainerListenerImpl* GetContainerListenerImpl() const {
      return container_listener_.get();
    }
  
    TremplinListenerImpl* GetTremplinListenerImpl() const {
      return tremplin_listener_.get();
    }
  
    CrashListenerImpl* GetCrashListenerImpl() const {
      return crash_listener_.get();
    }
  
    // For testing only. Pretend that the Tremplin server for the given VM is
    // actually at |tremplin_address| instead of the normal vsock address. Must
    // be called after the VM is created but before the corresponding
    // ConnectTremplin is called.
    bool SetTremplinStubOfVmForTesting(
        const std::string& owner_id,
        const std::string& vm_name,
        std::unique_ptr<vm_tools::tremplin::Tremplin::StubInterface>
            mock_tremplin_stub);
  
    // For testing only. Force the given VM to add a container with the indicated
    // security token. A VM with |owner_id|, |vm_name| must already exist. This is
    // the only way to get a consistent security token for unit tests & fuzz
    // tests. Returns true on success.
    bool CreateContainerWithTokenForTesting(const std::string& owner_id,
                                            const std::string& vm_name,
                                            const std::string& container_name,
                                            const std::string& container_token);
  
    // Stop Service from starting GRPC servers in a testing environment. Must
    // be called before calling Service::Init (and therefore Service::Create).
    static void DisableGrpcForTesting();
  
    // Connect to the Tremplin instance on the VM with the given |cid|.
    void ConnectTremplin(const uint32_t cid,
                         bool* result,
                         base::WaitableEvent* event);
  
    // The status of an ongoing LXD container create operation.
    enum class CreateStatus {
      UNKNOWN,
      CREATED,
      DOWNLOAD_TIMED_OUT,
      CANCELLED,
      FAILED,
    };
  
    // The status of an ongoing LXD container start operation.
    enum class StartStatus {
      UNKNOWN,
      STARTED,
      CANCELLED,
      FAILED,
    };
  
    // Notifies the service that a VM with |cid| has finished its create
    // operation of |container_name| with |status|. |failure_reason| will describe
    // the failure reason if status != CREATED. Sets |result| to true if the VM
    // cid is known. Signals |event| when done.
    void LxdContainerCreated(const uint32_t cid,
                             std::string container_name,
                             CreateStatus status,
                             std::string failure_reason,
                             bool* result,
                             base::WaitableEvent* event);
  
    // Notifies the service that a VM with |cid| is downloading a container
    // |container_name| with |download_progress| percentage complete. Sets
    // |result| to true if the VM cid is known. Signals |event| when done.
    void LxdContainerDownloading(const uint32_t cid,
                                 std::string container_name,
                                 int download_progress,
                                 bool* result,
                                 base::WaitableEvent* event);
  
    // Notifies the service that a VM with |cid| has finished its delete
    // operation of |container_name| with |status|. |failure_reason| will describe
    // the failure reason if status != DELETED. Sets |result| to true if the VM
    // cid is known. Signals |event| when done.
    void LxdContainerDeleted(
        const uint32_t cid,
        std::string container_name,
        vm_tools::tremplin::ContainerDeletionProgress::Status status,
        std::string failure_reason,
        bool* result,
        base::WaitableEvent* event);
  
    // Notifies the service that a VM with |cid| is starting a container
    // |container_name| with status |status|. |failure_reason| will describe the
    // failure reason if status == FAILED. Sets |result| to true if the VM cid
    // is known. Signals |event| when done.
    void LxdContainerStarting(const uint32_t cid,
                              std::string container_name,
                              StartStatus status,
                              std::string failure_reason,
                              bool* result,
                              base::WaitableEvent* event);
  
    // Notifies the service that a container with |container_token| and running
    // in a VM |cid| has completed startup. Sets |result| to true if this maps to
    // a currently running VM and |container_token| matches a security token for
    // that VM; false otherwise. Signals |event| when done.
    void ContainerStartupCompleted(const std::string& container_token,
                                   const uint32_t cid,
                                   const uint32_t garcon_vsock_port,
                                   bool* result,
                                   base::WaitableEvent* event);
  
    // Notifies the service that a container with |container_name| or
    // |container_token| and running in a VM with |cid| is shutting down. Sets
    // |result| to true if this maps to a currently running VM and
    // |container_token| matches a security token for that VM; false otherwise.
    // Signals |event| when done.  Callers from within the VM (tremplin) may set
    // |container_name|, but callers from wihtin a container (garcon) should not
    // be trusted to use |container_name| and must use |container_token|.
    void ContainerShutdown(std::string container_name,
                           std::string container_token,
                           const uint32_t cid,
                           bool* result,
                           base::WaitableEvent* event);
  
    // Notifies the service of a change in |listening_tcp4_ports| for the VM with
    // |cid|. Sets |result| to true if this maps to a currently running VM; false
    // otherwise. Signals |event| when done.
    void UpdateListeningPorts(
        std::map<std::string, std::vector<uint16_t>> listening_tcp4_ports,
        const uint32_t cid,
        bool* result,
        base::WaitableEvent* event);
  
    // Sends a D-Bus signal to inform listeners on update for the progress or
    // completion of container export. It will use |cid| to resolve the request to
    // a VM. |progress_signal| should have all related fields set |result| is set
    // to true on success, false otherwise. Signals |event| when done.
    void ContainerExportProgress(
        const uint32_t cid,
        ExportLxdContainerProgressSignal* progress_signal,
        bool* result,
        base::WaitableEvent* event);
  
    // Sends a D-Bus signal to inform listeners on update for the progress or
    // completion of container import. It will use |cid| to resolve the request to
    // a VM. |progress_signal| should have all related fields set |result| is set
    // to true on success, false otherwise. Signals |event| when done.
    void ContainerImportProgress(
        const uint32_t cid,
        ImportLxdContainerProgressSignal* progress_signal,
        bool* result,
        base::WaitableEvent* event);
  
    // Sends a D-Bus signal to inform listeners of progress or completion of a
    // container upgrade. It will use |cid| to resolve the request to
    // a VM. |progress_signal| should have all related fields set |result| is set
    // to true on success, false otherwise. Signals |event| when done.
    void ContainerUpgradeProgress(const uint32_t cid,
                                  UpgradeContainerProgressSignal* progress_signal,
                                  bool* result,
                                  base::WaitableEvent* event);
  
    // Sends a D-Bus signal to inform listeners of progress or completion of
    // starting lxd. It will use |cid| to resolve the request to a VM.
    // |progress_signal| should have all related fields set. |result| is set to
    // true on success, false otherwise. Signals |event| when done.
    void StartLxdProgress(const uint32_t cid,
                          StartLxdProgressSignal* progress_signal,
                          bool* result,
                          base::WaitableEvent* event);
  
    void PendingUpdateApplicationListCalls(const std::string& container_token,
                                           const uint32_t cid,
                                           const uint32_t count,
                                           bool* result,
                                           base::WaitableEvent* event);
  
    // This will send a D-Bus message to Chrome to inform it of the current
    // installed application list for a container. It will use |cid| to
    // resolve the request to a VM and then |container_token| to resolve it to a
    // container. |app_list| should be populated with the list of installed
    // applications but the vm & container names should be left blank; it must
    // remain valid for the lifetime of this call. |result| is set to true on
    // success, false otherwise. Signals |event| when done.
    void UpdateApplicationList(const std::string& container_token,
                               const uint32_t cid,
                               vm_tools::apps::ApplicationList* app_list,
                               bool* result,
                               base::WaitableEvent* event);
  
    // Sends a D-Bus message to Chrome to tell it to open the |url| in a new tab.
    // |result| is set to true on success, false otherwise. Signals
    // |event| when done.
    void OpenUrl(const std::string& container_token,
                 const std::string& url,
                 uint32_t cid,
                 bool* result,
                 base::WaitableEvent* event);
  
    // Sends a D-Bus signal to inform listeners on update for the progress or
    // completion of a Linux package install. It will use |cid| to
    // resolve the request to a VM and then |container_token| to resolve it to a
    // container. |progress_signal| should have all related fields from the
    // container request set in it. |result| is set to true on success, false
    // otherwise. Signals |event| when done.
    void InstallLinuxPackageProgress(
        const std::string& container_token,
        const uint32_t cid,
        InstallLinuxPackageProgressSignal* progress_signal,
        bool* result,
        base::WaitableEvent* event);
  
    // Sends a D-Bus signal to inform Chrome about the progress or completion of a
    // Linux package uninstall. It will use |cid| to resolve the request to a VM
    // and then |container_token| to resolve it to a container. |progress_signal|
    // should have all related fields from the container request set in it.
    // |result| is set to true on success, false otherwise. Signals |event| when
    // done.
    void UninstallPackageProgress(const std::string& container_token,
                                  const uint32_t cid,
                                  UninstallPackageProgressSignal* progress_signal,
                                  bool* result,
                                  base::WaitableEvent* event);
  
    // Sends a D-Bus signal to inform listeners on update for the progress or
    // completion of a Ansible playbook application. It will use |cid| to
    // resolve the request to a VM and then |container_token| to resolve it to a
    // container. |progress_signal| should have all related fields from the
    // container request set in it. |result| is set to true on success, false
    // otherwise. Signals |event| when done.
    void ApplyAnsiblePlaybookProgress(
        const std::string& container_token,
        const uint32_t cid,
        ApplyAnsiblePlaybookProgressSignal* progress_signal,
        bool* result,
        base::WaitableEvent* event);
  
    // Sends a D-Bus message to Chrome to tell it to open a terminal that is
    // connected back to the VM/container and if there are params in
    // |terminal_params| then those should be executed in that terminal.
    // It will use |cid| to resolve the request to a VM and then
    // |container_token| to resolve it to a container.  |result| is set to true on
    // success, false otherwise. Signals |event| when done.
    void OpenTerminal(const std::string& container_token,
                      vm_tools::apps::TerminalParams terminal_params,
                      const uint32_t cid,
                      bool* result,
                      base::WaitableEvent* event);
  
    // Sends a D-Bus message to Chrome to update the list of file extensions to
    // MIME type mapping in the container, the mappings are contained in
    // |mime_types|. It will use |cid| to resolve the request to a VM and then
    // |container_token| to resolve it to a container.  |result| is set to true on
    // success, false otherwise. Signals |event| when done.
    void UpdateMimeTypes(const std::string& container_token,
                         vm_tools::apps::MimeTypes mime_types,
                         const uint32_t cid,
                         bool* result,
                         base::WaitableEvent* event);
  
    // Sends a D-Bus signal to inform that a file has changed within the watched
    // directory. It will use |cid| to resolve the request to a VM and then
    // |container_token| to resolve it to a container. |triggered_signal| should
    // have all related fields from the container request set in it. |result| is
    // set to true on success, false otherwise. Signals |event| when done.
    void FileWatchTriggered(const std::string& container_token,
                            const uint32_t cid,
                            FileWatchTriggeredSignal* triggered_signal,
                            bool* result,
                            base::WaitableEvent* event);
  
    // Gets the VirtualMachine that corresponds to a container at |cid|
    // or the |vm_token| for the VM itself and sets |vm_out| to the
    // VirtualMachine, |owner_id_out| to the owner id of the VM, and |name_out| to
    // the name of the VM. Returns false if no such mapping exists.
    bool GetVirtualMachineForCidOrToken(const uint32_t cid,
                                        const std::string& vm_token,
                                        VirtualMachine** vm_out,
                                        std::string* owner_id_out,
                                        std::string* name_out);
  
   private:
    // Sends the |signal_name| D-Bus signal with |signal_proto| as its contents.
    // It will use |cid| to lookup VM and owner, and set these fields on
    // |signal_proto| before sending it.
    template <typename T>
    bool SendSignal(const std::string& signal_name,
                    const uint32_t cid,
                    T* signal_proto) {
      DCHECK(sequence_checker_.CalledOnValidSequence());
      CHECK(signal_proto);
      VirtualMachine* vm;
      std::string owner_id;
      std::string vm_name;
  
      if (!GetVirtualMachineForCidOrToken(cid, "", &vm, &owner_id, &vm_name)) {
        LOG(ERROR) << "Could not get virtual machine for cid";
        return false;
      }
  
      dbus::Signal signal(kVmCiceroneInterface, signal_name);
      signal_proto->set_vm_name(std::move(vm_name));
      signal_proto->set_owner_id(std::move(owner_id));
      dbus::MessageWriter(&signal).AppendProtoAsArrayOfBytes(*signal_proto);
      exported_object_->SendSignal(&signal);
      return true;
    }
  
    // Sends the |signal_name| D-Bus signal with |signal_proto| as its contents.
    // It will use |cid| and |container_token| to lookup VM, owner, and container
    // name, and set these fields on |signal_proto| before sending it.
    template <typename T>
    bool SendSignal(const std::string& signal_name,
                    const std::string& container_token,
                    const uint32_t cid,
                    T* signal_proto) {
      DCHECK(sequence_checker_.CalledOnValidSequence());
      CHECK(signal_proto);
      VirtualMachine* vm;
      std::string owner_id;
      std::string vm_name;
  
      if (!GetVirtualMachineForCidOrToken(cid, container_token, &vm, &owner_id,
                                          &vm_name)) {
        LOG(ERROR) << "Could not get virtual machine for cid";
        return false;
      }
  
      std::string container_name = vm->GetContainerNameForToken(container_token);
      if (container_name.empty()) {
        LOG(ERROR) << "Could not get container name for token";
        return false;
      }
  
      dbus::Signal signal(kVmCiceroneInterface, signal_name);
      signal_proto->set_vm_name(std::move(vm_name));
      signal_proto->set_container_name(std::move(container_name));
      signal_proto->set_owner_id(std::move(owner_id));
      dbus::MessageWriter(&signal).AppendProtoAsArrayOfBytes(*signal_proto);
      exported_object_->SendSignal(&signal);
      return true;
    }
  
    explicit Service(base::Closure quit_closure, scoped_refptr<dbus::Bus> bus);
    Service(const Service&) = delete;
    Service& operator=(const Service&) = delete;
  
    // Initializes the service by exporting our DBus methods, taking ownership of
    // its name, and starting our gRPC servers. If |unix_socket_path_for_testing|
    // has a value, the services are bound only to an AF_UNIX socket in that
    // directory instead of the normal VSOCK and AF_UNIX socket.
    bool Init(const base::Optional<base::FilePath>& unix_socket_path_for_testing);
  
    // Handles the termination of a child process.
    void HandleChildExit();
  
    // Handles a SIGTERM.
    void HandleSigterm();
  
    // Handles notification a VM is starting.
    std::unique_ptr<dbus::Response> NotifyVmStarted(
        dbus::MethodCall* method_call);
  
    // Handles a notification a VM is stopping.
    std::unique_ptr<dbus::Response> NotifyVmStopping(
        dbus::MethodCall* method_call);
  
    // Handles a notification a VM has stopped.
    std::unique_ptr<dbus::Response> NotifyVmStopped(
        dbus::MethodCall* method_call);
  
    // Handles a request to get a security token to associate with a container.
    std::unique_ptr<dbus::Response> GetContainerToken(
        dbus::MethodCall* method_call);
  
    // Handles a request to launch an application in a container.
    std::unique_ptr<dbus::Response> LaunchContainerApplication(
        dbus::MethodCall* method_call);
  
    // Handles a request to get application icons in a container.
    std::unique_ptr<dbus::Response> GetContainerAppIcon(
        dbus::MethodCall* method_call);
  
    // Handles a request to launch vshd in a container.
    std::unique_ptr<dbus::Response> LaunchVshd(dbus::MethodCall* method_call);
  
    // Handles a request to get Linux package info from a container.
    std::unique_ptr<dbus::Response> GetLinuxPackageInfo(
        dbus::MethodCall* method_call);
  
    // Handles a request to install a Linux package file in a container.
    std::unique_ptr<dbus::Response> InstallLinuxPackage(
        dbus::MethodCall* method_call);
  
    // Handles a request to uninstall the Linux package that owns the indicated
    // .desktop file.
    std::unique_ptr<dbus::Response> UninstallPackageOwningFile(
        dbus::MethodCall* method_call);
  
    // Handles a request to create an LXD container.
    std::unique_ptr<dbus::Response> CreateLxdContainer(
        dbus::MethodCall* method_call);
  
    // Handles a request to delete an LXD container.
    std::unique_ptr<dbus::Response> DeleteLxdContainer(
        dbus::MethodCall* method_call);
  
    // Handles a request to start an LXD container.
    std::unique_ptr<dbus::Response> StartLxdContainer(
        dbus::MethodCall* method_call);
  
    // Handles a request to set the default timezone for an LXD instance.
    std::unique_ptr<dbus::Response> SetTimezone(dbus::MethodCall* method_call);
  
    // Handles a request to get the primary username for an LXD container.
    std::unique_ptr<dbus::Response> GetLxdContainerUsername(
        dbus::MethodCall* method_call);
  
    // Handles a request to set up the user for an LXD container.
    std::unique_ptr<dbus::Response> SetUpLxdContainerUser(
        dbus::MethodCall* method_call);
  
    // Handles a request to export an LXD container.
    std::unique_ptr<dbus::Response> ExportLxdContainer(
        dbus::MethodCall* method_call);
  
    // Handles a request to cancel an ongoing LXD container export.
    std::unique_ptr<dbus::Response> CancelExportLxdContainer(
        dbus::MethodCall* method_call);
  
    // Handles a request to import an LXD container.
    std::unique_ptr<dbus::Response> ImportLxdContainer(
        dbus::MethodCall* method_call);
  
    // Handles a request to cancel an ongoing LXD container import.
    std::unique_ptr<dbus::Response> CancelImportLxdContainer(
        dbus::MethodCall* method_call);
  
    // Handles a request to connect to chunnel.
    std::unique_ptr<dbus::Response> ConnectChunnel(dbus::MethodCall* method_call);
  
    // Handles a request to get debug information.
    std::unique_ptr<dbus::Response> GetDebugInformation(
        dbus::MethodCall* method_call);
  
    // Handles a request to apply Ansible playbook to a container.
    std::unique_ptr<dbus::Response> ApplyAnsiblePlaybook(
        dbus::MethodCall* method_call);
  
    // Handles a request to allow sideloading Arc (android) apps from the
    // container.
    std::unique_ptr<dbus::Response> ConfigureForArcSideload(
        dbus::MethodCall* method_call);
  
    // Handles a request to upgrade a container.
    std::unique_ptr<dbus::Response> UpgradeContainer(
        dbus::MethodCall* method_call);
  
    // Handles a request to cancel an ongoing container upgrade.
    std::unique_ptr<dbus::Response> CancelUpgradeContainer(
        dbus::MethodCall* method_call);
  
    // Handles a request to start LXD.
    std::unique_ptr<dbus::Response> StartLxd(dbus::MethodCall* method_call);
  
    // Handles a request to add a file watch.
    std::unique_ptr<dbus::Response> AddFileWatch(dbus::MethodCall* method_call);
  
    // Handles a request to remove a file watch.
    std::unique_ptr<dbus::Response> RemoveFileWatch(
        dbus::MethodCall* method_call);
  
    // Handles a request to add a mapping between vsh and the session data such as
    // the container shell pid.
    std::unique_ptr<dbus::Response> RegisterVshSession(
        dbus::MethodCall* method_call);
  
    // Handles a request to retrieve vsh session data.
    std::unique_ptr<dbus::Response> GetVshSession(dbus::MethodCall* method_call);
  
    // Gets the container's SSH keys from concierge.
    bool GetContainerSshKeys(const std::string& owner_id,
                             const std::string& vm_name,
                             const std::string& container_name,
                             std::string* host_pubkey_out,
                             std::string* host_privkey_out,
                             std::string* container_pubkey_out,
                             std::string* container_privkey_out,
                             std::string* hostname_out,
                             std::string* error_out);
  
    // Registers |hostname| and |ip| with the hostname resolver service so that
    // the container is reachable from a known hostname.
    void RegisterHostname(const std::string& hostname, const std::string& ip);
  
    // Unregisters containers associated with this |vm| with |owner_id| and
    // |vm_name|.  All hostnames are removed from the hostname resolver service,
    // and the ContainerShutdown signal is sent via D-Bus.
    void UnregisterVmContainers(VirtualMachine* vm,
                                const std::string& owner_id,
                                const std::string& vm_name);
  
    // Unregisters |hostname| with the hostname resolver service.
    void UnregisterHostname(const std::string& hostname);
  
    // Callback for when the crosdns D-Bus service goes online (or is online
    // already) so we can then register the NameOwnerChanged callback.
    void OnCrosDnsServiceAvailable(bool service_is_available);
  
    // Callback for when the crosdns D-Bus service restarts so we can
    // re-register any of our hostnames that are active.
    void OnCrosDnsNameOwnerChanged(const std::string& old_owner,
                                   const std::string& new_owner);
  
    // Callback for when the localtime file is changed so that we can update
    // the timezone for containers.
    void OnLocaltimeFileChanged(const base::FilePath& path, bool error);
  
    void OnSignalReadable();
  
    // Handles default service changes from shill.
    void OnDefaultNetworkServiceChanged();
  
    // Send all listening ports to chunneld.
    void SendListeningPorts();
  
    // Gets a VirtualMachine pointer to the registered VM with corresponding
    // |owner_id| and |vm_name|. Returns a nullptr if not found.
    VirtualMachine* FindVm(const std::string& owner_id,
                           const std::string& vm_name);
  
    // File descriptor for SIGTERM/SIGCHLD event.
    base::ScopedFD signal_fd_;
    std::unique_ptr<base::FileDescriptorWatcher::Controller> watcher_;
  
    // The shill D-Bus client.
    std::unique_ptr<ShillClient> shill_client_;
  
    // Key for VMs in the map, which is the owner ID and VM name as a pair.
    using VmKey = std::pair<std::string, std::string>;
    // Running VMs.
    std::map<VmKey, std::unique_ptr<VirtualMachine>> vms_;
  
    // Map of TCP4 ports to forwarding targets.
    using TcpForwardTarget = std::pair<std::string, std::string>;
    std::map<uint16_t, TcpForwardTarget> listening_tcp4_ports_;
  
    // Connection to the system bus.
    scoped_refptr<dbus::Bus> bus_;
    dbus::ExportedObject* exported_object_;             // Owned by |bus_|.
    dbus::ObjectProxy* vm_applications_service_proxy_;  // Owned by |bus_|.
    dbus::ObjectProxy* url_handler_service_proxy_;      // Owned by |bus_|.
    dbus::ObjectProxy* chunneld_service_proxy_;         // Owned by |bus_|.
    dbus::ObjectProxy* crosdns_service_proxy_;          // Owned by |bus_|.
    dbus::ObjectProxy* concierge_service_proxy_;        // Owned by |bus_|.
  
    // The ContainerListener service.
    std::unique_ptr<ContainerListenerImpl> container_listener_;
  
    // Thread on which the ContainerListener service lives.
    base::Thread grpc_thread_container_{"gRPC Container Server Thread"};
  
    // The server where the ContainerListener service lives.
    std::shared_ptr<grpc::Server> grpc_server_container_;
  
    // The TremplinListener service.
    std::unique_ptr<TremplinListenerImpl> tremplin_listener_;
  
    // Thread on which the TremplinListener service lives.
    base::Thread grpc_thread_tremplin_{"gRPC Tremplin Server Thread"};
  
    // The server where the TremplinListener service lives.
    std::shared_ptr<grpc::Server> grpc_server_tremplin_;
  
    // The CrashListener service.
    std::unique_ptr<CrashListenerImpl> crash_listener_;
  
    // Thread on which the CrashListener service lives.
    base::Thread grpc_thread_crash_{"gRPC Crash Server Thread"};
  
    // The server where the CrashListener service lives.
    std::shared_ptr<grpc::Server> grpc_server_crash_;
  
    // Closure that's posted to the current thread's TaskRunner when the service
    // receives a SIGTERM.
    base::Closure quit_closure_;
  
    // Ensure calls are made on the right thread.
    base::SequenceChecker sequence_checker_;
  
    // Map of hostnames/IPs we have registered so we can re-register them if the
    // resolver service restarts.
    std::map<std::string, std::string> hostname_mappings_;
  
    // IP address registered for 'linuxhost' so we can swap this out on OpenUrl
    // calls.
    std::string linuxhost_ip_;
  
    // Owner of the primary VM, we only do hostname mappings for the primary VM.
    std::string primary_owner_id_;
  
    // Handle to the SSH port forwarding process.
    brillo::ProcessImpl ssh_process_;
  
    // Watcher to monitor changes to the system timezone file.
    base::FilePathWatcher localtime_watcher_;
  
    // Should Service start GRPC servers for ContainerListener and
    // TremplinListener Used for testing
    static bool run_grpc_;
  
    base::WeakPtrFactory<Service> weak_ptr_factory_;
  };
  
  }  // namespace cicerone
  }  // namespace vm_tools
  
  #endif  // VM_TOOLS_CICERONE_SERVICE_H_
  