blob: 95d68551c88255c1c3327f211e8621c3ba504890 [file] [log] [blame]
// Copyright 2019 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_SERVICES_DEVICE_SYNC_CRYPTAUTH_DEVICE_NOTIFIER_IMPL_H_
#define CHROMEOS_SERVICES_DEVICE_SYNC_CRYPTAUTH_DEVICE_NOTIFIER_IMPL_H_
#include <memory>
#include <ostream>
#include <string>
#include "base/callback.h"
#include "base/containers/flat_set.h"
#include "base/containers/queue.h"
#include "base/macros.h"
#include "base/timer/timer.h"
#include "chromeos/services/device_sync/cryptauth_device_notifier.h"
#include "chromeos/services/device_sync/cryptauth_feature_type.h"
#include "chromeos/services/device_sync/network_request_error.h"
#include "chromeos/services/device_sync/proto/cryptauth_client_app_metadata.pb.h"
#include "chromeos/services/device_sync/proto/cryptauth_common.pb.h"
#include "chromeos/services/device_sync/proto/cryptauth_devicesync.pb.h"
namespace chromeos {
namespace device_sync {
class ClientAppMetadataProvider;
class CryptAuthClient;
class CryptAuthClientFactory;
class CryptAuthGCMManager;
// An implementation of CryptAuthDeviceNotifier, using instances of
// CryptAuthClient to make the BatchNotifyGroupDevices API calls to CryptAuth.
// The requests made via NotifyDevices() are queued and processed sequentially.
// This implementation handles timeouts internally, so a callback passed to
// NotifyDevices() is always guaranteed to be invoked.
class CryptAuthDeviceNotifierImpl : public CryptAuthDeviceNotifier {
public:
class Factory {
public:
static std::unique_ptr<CryptAuthDeviceNotifier> Create(
ClientAppMetadataProvider* client_app_metadata_provider,
CryptAuthClientFactory* client_factory,
CryptAuthGCMManager* gcm_manager,
std::unique_ptr<base::OneShotTimer> timer =
std::make_unique<base::OneShotTimer>());
static void SetFactoryForTesting(Factory* test_factory);
protected:
virtual ~Factory();
virtual std::unique_ptr<CryptAuthDeviceNotifier> CreateInstance(
ClientAppMetadataProvider* client_app_metadata_provider,
CryptAuthClientFactory* client_factory,
CryptAuthGCMManager* gcm_manager,
std::unique_ptr<base::OneShotTimer> timer) = 0;
private:
static Factory* test_factory_;
};
~CryptAuthDeviceNotifierImpl() override;
private:
enum class State {
kIdle,
kWaitingForClientAppMetadata,
kWaitingForBatchNotifyGroupDevicesResponse
};
friend std::ostream& operator<<(std::ostream& stream, const State& state);
static base::Optional<base::TimeDelta> GetTimeoutForState(State state);
struct Request {
Request(const base::flat_set<std::string>& device_ids,
cryptauthv2::TargetService target_service,
CryptAuthFeatureType feature_type,
base::OnceClosure success_callback,
base::OnceCallback<void(NetworkRequestError)> error_callback);
Request(Request&& request);
~Request();
base::flat_set<std::string> device_ids;
cryptauthv2::TargetService target_service;
CryptAuthFeatureType feature_type;
base::OnceClosure success_callback;
base::OnceCallback<void(NetworkRequestError)> error_callback;
};
CryptAuthDeviceNotifierImpl(
ClientAppMetadataProvider* client_app_metadata_provider,
CryptAuthClientFactory* client_factory,
CryptAuthGCMManager* gcm_manager,
std::unique_ptr<base::OneShotTimer> timer);
// CryptAuthDeviceNotifier:
void NotifyDevices(
const base::flat_set<std::string>& device_ids,
cryptauthv2::TargetService target_service,
CryptAuthFeatureType feature_type,
base::OnceClosure success_callback,
base::OnceCallback<void(NetworkRequestError)> error_callback) override;
void SetState(State state);
void OnTimeout();
void ProcessRequestQueue();
void OnClientAppMetadataFetched(
const base::Optional<cryptauthv2::ClientAppMetadata>&
client_app_metadata);
void OnBatchNotifyGroupDevicesSuccess(
const cryptauthv2::BatchNotifyGroupDevicesResponse& response);
void OnBatchNotifyGroupDevicesFailure(NetworkRequestError error);
void FinishAttempt(base::Optional<NetworkRequestError> error);
State state_ = State::kIdle;
base::TimeTicks last_state_change_timestamp_;
base::Optional<cryptauthv2::ClientAppMetadata> client_app_metadata_;
base::queue<Request> pending_requests_;
ClientAppMetadataProvider* client_app_metadata_provider_ = nullptr;
CryptAuthClientFactory* client_factory_ = nullptr;
CryptAuthGCMManager* gcm_manager_ = nullptr;
std::unique_ptr<CryptAuthClient> cryptauth_client_;
std::unique_ptr<base::OneShotTimer> timer_;
base::WeakPtrFactory<CryptAuthDeviceNotifierImpl> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(CryptAuthDeviceNotifierImpl);
};
} // namespace device_sync
} // namespace chromeos
#endif // CHROMEOS_SERVICES_DEVICE_SYNC_CRYPTAUTH_DEVICE_NOTIFIER_IMPL_H_