blob: 792c48247ac1e0584af904c02e8627f4e628cd2b [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_HOST_SCANNER_OPERATION_H_
#define CHROMEOS_COMPONENTS_TETHER_HOST_SCANNER_OPERATION_H_
#include <map>
#include <vector>
#include "base/macros.h"
#include "base/observer_list.h"
#include "base/time/clock.h"
#include "chromeos/components/multidevice/remote_device_ref.h"
#include "chromeos/components/tether/message_transfer_operation.h"
namespace chromeos {
namespace device_sync {
class DeviceSyncClient;
} // namespace device_sync
namespace secure_channel {
class SecureChannelClient;
} // namespace secure_channel
namespace tether {
class ConnectionPreserver;
class HostScanDevicePrioritizer;
class MessageWrapper;
class TetherHostResponseRecorder;
// Operation used to perform a host scan. Attempts to connect to each of the
// devices passed and sends a TetherAvailabilityRequest to each connected device
// once an authenticated channel has been established; once a response has been
// received, HostScannerOperation alerts observers of devices which can provide
// a tethering connection.
class HostScannerOperation : public MessageTransferOperation {
public:
class Factory {
public:
static std::unique_ptr<HostScannerOperation> Create(
const multidevice::RemoteDeviceRefList& devices_to_connect,
device_sync::DeviceSyncClient* device_sync_client,
secure_channel::SecureChannelClient* secure_channel_client,
HostScanDevicePrioritizer* host_scan_device_prioritizer,
TetherHostResponseRecorder* tether_host_response_recorder,
ConnectionPreserver* connection_preserver);
static void SetFactoryForTesting(Factory* factory);
protected:
virtual ~Factory();
virtual std::unique_ptr<HostScannerOperation> CreateInstance(
const multidevice::RemoteDeviceRefList& devices_to_connect,
device_sync::DeviceSyncClient* device_sync_client,
secure_channel::SecureChannelClient* secure_channel_client,
HostScanDevicePrioritizer* host_scan_device_prioritizer,
TetherHostResponseRecorder* tether_host_response_recorder,
ConnectionPreserver* connection_preserver) = 0;
private:
static Factory* factory_instance_;
};
struct ScannedDeviceInfo {
ScannedDeviceInfo(multidevice::RemoteDeviceRef remote_device,
const DeviceStatus& device_status,
bool setup_required);
~ScannedDeviceInfo();
friend bool operator==(const ScannedDeviceInfo& first,
const ScannedDeviceInfo& second);
multidevice::RemoteDeviceRef remote_device;
DeviceStatus device_status;
bool setup_required;
};
class Observer {
public:
// Invoked once with an empty list when the operation begins, then invoked
// repeatedly once each result comes in. After all devices have been
// processed, the callback is invoked one final time with
// |is_final_scan_result| = true.
virtual void OnTetherAvailabilityResponse(
const std::vector<ScannedDeviceInfo>& scanned_device_list_so_far,
const multidevice::RemoteDeviceRefList&
gms_core_notifications_disabled_devices,
bool is_final_scan_result) = 0;
};
~HostScannerOperation() override;
void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer);
protected:
HostScannerOperation(
const multidevice::RemoteDeviceRefList& devices_to_connect,
device_sync::DeviceSyncClient* device_sync_client,
secure_channel::SecureChannelClient* secure_channel_client,
HostScanDevicePrioritizer* host_scan_device_prioritizer,
TetherHostResponseRecorder* tether_host_response_recorder,
ConnectionPreserver* connection_preserver);
void NotifyObserversOfScannedDeviceList(bool is_final_scan_result);
// MessageTransferOperation:
void OnDeviceAuthenticated(
multidevice::RemoteDeviceRef remote_device) override;
void OnMessageReceived(std::unique_ptr<MessageWrapper> message_wrapper,
multidevice::RemoteDeviceRef remote_device) override;
void OnOperationStarted() override;
void OnOperationFinished() override;
MessageType GetMessageTypeForConnection() override;
std::vector<ScannedDeviceInfo> scanned_device_list_so_far_;
private:
friend class HostScannerOperationTest;
FRIEND_TEST_ALL_PREFIXES(HostScannerOperationTest,
DevicesArePrioritizedDuringConstruction);
FRIEND_TEST_ALL_PREFIXES(HostScannerOperationTest, RecordsResponseDuration);
FRIEND_TEST_ALL_PREFIXES(HostScannerOperationTest, ErrorResponses);
FRIEND_TEST_ALL_PREFIXES(HostScannerOperationTest, NotificationsDisabled);
FRIEND_TEST_ALL_PREFIXES(HostScannerOperationTest, TetherAvailable);
FRIEND_TEST_ALL_PREFIXES(HostScannerOperationTest, LastProvisioningFailed);
FRIEND_TEST_ALL_PREFIXES(HostScannerOperationTest, SetupRequired);
FRIEND_TEST_ALL_PREFIXES(HostScannerOperationTest, TestMultipleDevices);
using MessageTransferOperation::UnregisterDevice;
void SetTestDoubles(base::Clock* clock_for_test,
scoped_refptr<base::TaskRunner> test_task_runner);
void RecordTetherAvailabilityResponseDuration(const std::string device_id);
TetherHostResponseRecorder* tether_host_response_recorder_;
ConnectionPreserver* connection_preserver_;
base::Clock* clock_;
scoped_refptr<base::TaskRunner> task_runner_;
base::ObserverList<Observer>::Unchecked observer_list_;
multidevice::RemoteDeviceRefList gms_core_notifications_disabled_devices_;
std::map<std::string, base::Time>
device_id_to_tether_availability_request_start_time_map_;
base::WeakPtrFactory<HostScannerOperation> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(HostScannerOperation);
};
} // namespace tether
} // namespace chromeos
#endif // CHROMEOS_COMPONENTS_TETHER_HOST_SCANNER_OPERATION_H_