blob: 84b1c733a89097356dd63ae12253c72587573b0a [file] [log] [blame]
// Copyright 2017 The Chromium 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 CHROMEOS_COMPONENTS_TETHER_MESSAGE_TRANSFER_OPERATION_H_
#define CHROMEOS_COMPONENTS_TETHER_MESSAGE_TRANSFER_OPERATION_H_
#include <map>
#include <vector>
#include "base/macros.h"
#include "base/optional.h"
#include "base/timer/timer.h"
#include "base/unguessable_token.h"
#include "chromeos/components/tether/proto/tether.pb.h"
#include "chromeos/services/device_sync/public/cpp/device_sync_client.h"
#include "chromeos/services/secure_channel/public/cpp/client/client_channel.h"
#include "chromeos/services/secure_channel/public/cpp/client/connection_attempt.h"
#include "chromeos/services/secure_channel/public/cpp/client/secure_channel_client.h"
#include "chromeos/services/secure_channel/public/cpp/shared/connection_priority.h"
#include "chromeos/services/secure_channel/public/mojom/secure_channel.mojom.h"
namespace chromeos {
namespace tether {
class MessageWrapper;
class TimerFactory;
// Abstract base class used for operations which send and/or receive messages
// from remote devices.
class MessageTransferOperation {
public:
MessageTransferOperation(
const multidevice::RemoteDeviceRefList& devices_to_connect,
secure_channel::ConnectionPriority connection_priority,
device_sync::DeviceSyncClient* device_sync_client,
secure_channel::SecureChannelClient* secure_channel_client);
virtual ~MessageTransferOperation();
// Initializes the operation by registering device connection listeners with
// SecureChannel.
void Initialize();
protected:
// Unregisters |remote_device| for the MessageType returned by
// GetMessageTypeForConnection().
void UnregisterDevice(multidevice::RemoteDeviceRef remote_device);
// Sends |message_wrapper|'s message to |remote_device| and returns the
// associated message's sequence number.
int SendMessageToDevice(multidevice::RemoteDeviceRef remote_device,
std::unique_ptr<MessageWrapper> message_wrapper);
// Callback executed whena device 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 |remote_device| as soon as an
// authenticated channel has been established to that device.
virtual void OnDeviceAuthenticated(
multidevice::RemoteDeviceRef remote_device) {}
// Callback executed when a tether protocol message is received. Should be
// overriden by derived classes which intend to handle messages received from
// |remote_device|.
virtual void OnMessageReceived(
std::unique_ptr<MessageWrapper> message_wrapper,
multidevice::RemoteDeviceRef remote_device) {}
// Callback executed when any message is received on the "magic_tether"
// feature.
virtual void OnMessageReceived(const std::string& device_id,
const std::string& payload);
// Callback executed a tether protocol message is sent. |sequence_number| is
// the value returned by SendMessageToDevice().
virtual void OnMessageSent(int sequence_number) {}
// 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();
multidevice::RemoteDeviceRefList& remote_devices() { return remote_devices_; }
private:
friend class ConnectTetheringOperationTest;
friend class DisconnectTetheringOperationTest;
friend class HostScannerOperationTest;
friend class KeepAliveOperationTest;
friend class MessageTransferOperationTest;
class ConnectionAttemptDelegate
: public secure_channel::ConnectionAttempt::Delegate {
public:
ConnectionAttemptDelegate(
MessageTransferOperation* operation,
multidevice::RemoteDeviceRef remote_device,
std::unique_ptr<secure_channel::ConnectionAttempt> connection_attempt);
~ConnectionAttemptDelegate() override;
// secure_channel::ConnectionAttempt::Delegate:
void OnConnectionAttemptFailure(
secure_channel::mojom::ConnectionAttemptFailureReason reason) override;
void OnConnection(
std::unique_ptr<secure_channel::ClientChannel> channel) override;
private:
MessageTransferOperation* operation_;
multidevice::RemoteDeviceRef remote_device_;
std::unique_ptr<secure_channel::ConnectionAttempt> connection_attempt_;
};
class ClientChannelObserver : public secure_channel::ClientChannel::Observer {
public:
ClientChannelObserver(
MessageTransferOperation* operation,
multidevice::RemoteDeviceRef remote_device,
std::unique_ptr<secure_channel::ClientChannel> client_channel);
~ClientChannelObserver() override;
// secure_channel::ClientChannel::Observer:
void OnDisconnected() override;
void OnMessageReceived(const std::string& payload) override;
secure_channel::ClientChannel* channel() { return client_channel_.get(); }
private:
MessageTransferOperation* operation_;
multidevice::RemoteDeviceRef remote_device_;
std::unique_ptr<secure_channel::ClientChannel> client_channel_;
};
// 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;
void OnConnectionAttemptFailure(
multidevice::RemoteDeviceRef remote_device,
secure_channel::mojom::ConnectionAttemptFailureReason reason);
void OnConnection(multidevice::RemoteDeviceRef remote_device,
std::unique_ptr<secure_channel::ClientChannel> channel);
void OnDisconnected(multidevice::RemoteDeviceRef remote_device);
// Start the timer while waiting for a connection to |remote_device|. See
// |kConnectionTimeoutSeconds|.
void StartConnectionTimerForDevice(
multidevice::RemoteDeviceRef remote_device);
// Start the timer while waiting for messages to be sent to and received by
// |remote_device|. See |kDefaultMessageTimeoutSeconds|.
void StartMessageTimerForDevice(multidevice::RemoteDeviceRef remote_device);
void StartTimerForDevice(multidevice::RemoteDeviceRef remote_device,
uint32_t timeout_seconds);
void StopTimerForDeviceIfRunning(multidevice::RemoteDeviceRef remote_device);
void OnTimeout(multidevice::RemoteDeviceRef remote_device);
base::Optional<multidevice::RemoteDeviceRef> GetRemoteDevice(
const std::string& device_id);
void SetTimerFactoryForTest(
std::unique_ptr<TimerFactory> timer_factory_for_test);
multidevice::RemoteDeviceRefList remote_devices_;
device_sync::DeviceSyncClient* device_sync_client_;
secure_channel::SecureChannelClient* secure_channel_client_;
const secure_channel::ConnectionPriority connection_priority_;
std::unique_ptr<TimerFactory> timer_factory_;
bool initialized_ = false;
bool shutting_down_ = false;
MessageType message_type_for_connection_;
base::flat_map<multidevice::RemoteDeviceRef,
std::unique_ptr<ConnectionAttemptDelegate>>
remote_device_to_connection_attempt_delegate_map_;
base::flat_map<multidevice::RemoteDeviceRef,
std::unique_ptr<ClientChannelObserver>>
remote_device_to_client_channel_observer_map_;
int next_message_sequence_number_ = 0;
base::flat_map<multidevice::RemoteDeviceRef,
std::unique_ptr<base::OneShotTimer>>
remote_device_to_timer_map_;
base::WeakPtrFactory<MessageTransferOperation> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(MessageTransferOperation);
};
} // namespace tether
} // namespace chromeos
#endif // CHROMEOS_COMPONENTS_TETHER_MESSAGE_TRANSFER_OPERATION_H_