chromium/chromeos/ash/components/tether/message_transfer_operation.h

// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROMEOS_ASH_COMPONENTS_TETHER_MESSAGE_TRANSFER_OPERATION_H_
#define CHROMEOS_ASH_COMPONENTS_TETHER_MESSAGE_TRANSFER_OPERATION_H_

#include <map>
#include <optional>
#include <vector>

#include "base/memory/raw_ptr.h"
#include "base/timer/timer.h"
#include "base/unguessable_token.h"
#include "chromeos/ash/components/tether/host_connection.h"
#include "chromeos/ash/components/tether/message_wrapper.h"
#include "chromeos/ash/components/tether/proto/tether.pb.h"
#include "chromeos/ash/components/tether/tether_host.h"

namespace ash::timer_factory {
class TimerFactory;
}  // namespace ash::timer_factory

namespace ash::tether {

// Abstract base class used for operations which send and/or receive messages
// from remote devices.
class MessageTransferOperation : public HostConnection::PayloadListener {
 public:
  MessageTransferOperation(
      const TetherHost& tether_host,
      HostConnection::Factory::ConnectionPriority connection_priority,
      raw_ptr<HostConnection::Factory> host_connection_factory);

  MessageTransferOperation(const MessageTransferOperation&) = delete;
  MessageTransferOperation& operator=(const MessageTransferOperation&) = delete;

  ~MessageTransferOperation() override;

  // Initializes the operation by registering device connection listeners with
  // SecureChannel.
  void Initialize();

 protected:
  // Manually ends the operation.
  void StopOperation();

  // Callback executed when a host is authenticated (i.e., it is in a state
  // which allows messages to be sent/received). Should be overridden by derived
  // classes which intend to send a message to |tether_host_| as soon as an
  // authenticated channel has been established to that host.
  virtual void OnDeviceAuthenticated() {}

  void SendMessage(std::unique_ptr<MessageWrapper> message_wrapper,
                   HostConnection::OnMessageSentCallback on_message_sent);

  // HostConnection::PayloadListener:
  void OnMessageReceived(
      std::unique_ptr<MessageWrapper> message_wrapper) override {}

  void OnConnectionAttemptComplete(
      std::unique_ptr<HostConnection> host_connection);
  void OnDisconnected();

  // Callback executed when the operation has started (i.e., in Initialize()).
  virtual void OnOperationStarted() {}

  // Callback executed when the operation has finished (i.e., when all devices
  // have been unregistered).
  virtual void OnOperationFinished() {}

  // Returns the type of message that this operation intends to send.
  virtual MessageType GetMessageTypeForConnection() = 0;

  // The number of seconds that this operation should wait to let messages be
  // sent and received before unregistering a device after it has been
  // authenticated if it has not been explicitly unregistered. If
  // ShouldOperationUseTimeout() returns false, this method is never used.
  virtual uint32_t GetMessageTimeoutSeconds();

  const std::string GetDeviceId(bool truncate_for_logs) const;

 private:
  friend class ConnectTetheringOperationTest;
  friend class DisconnectTetheringOperationTest;
  friend class TetherAvailabilityOperationTest;
  friend class KeepAliveOperationTest;
  friend class MessageTransferOperationTest;

  // The maximum expected time to connect to a remote device, if it can be
  // connected to. This number has been determined by examining metrics.
  static constexpr const uint32_t kConnectionTimeoutSeconds = 15;

  // The default number of seconds an operation should wait to send and receive
  // messages before a timeout occurs. Once this amount of time passes, the
  // connection will be closed. Classes deriving from MessageTransferOperation
  // should override GetMessageTimeoutSeconds() if they desire a different
  // duration.
  static constexpr const uint32_t kDefaultMessageTimeoutSeconds = 10;

  // Start the timer while waiting for a connection to |remote_device|. See
  // |kConnectionTimeoutSeconds|.
  void StartConnectionTimerForDevice();

  // Start the timer while waiting for messages to be sent to and received by
  // |remote_device|. See |kDefaultMessageTimeoutSeconds|.
  void StartMessageTimerForDevice();

  void StartTimerForDevice(uint32_t timeout_seconds);
  void StopTimerForDeviceIfRunning();
  void OnTimeout();

  void SetTimerFactoryForTest(
      std::unique_ptr<ash::timer_factory::TimerFactory> timer_factory_for_test);

  TetherHost tether_host_;
  const HostConnection::Factory::ConnectionPriority connection_priority_;
  std::unique_ptr<HostConnection> host_connection_;
  raw_ptr<HostConnection::Factory> host_connection_factory_;

  std::unique_ptr<ash::timer_factory::TimerFactory> timer_factory_;

  bool initialized_ = false;
  bool shutting_down_ = false;
  MessageType message_type_for_connection_;

  std::unique_ptr<base::OneShotTimer> remote_device_timer_;
  base::WeakPtrFactory<MessageTransferOperation> weak_ptr_factory_{this};
};

}  // namespace ash::tether

#endif  // CHROMEOS_ASH_COMPONENTS_TETHER_MESSAGE_TRANSFER_OPERATION_H_