#ifndef DEVICE_FIDO_BIO_ENROLLMENT_HANDLER_H_
#define DEVICE_FIDO_BIO_ENROLLMENT_HANDLER_H_
#include <map>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "base/component_export.h"
#include "base/containers/flat_set.h"
#include "base/memory/raw_ptr.h"
#include "base/sequence_checker.h"
#include "device/fido/bio/enroller.h"
#include "device/fido/bio/enrollment.h"
#include "device/fido/fido_constants.h"
#include "device/fido/fido_discovery_factory.h"
#include "device/fido/fido_request_handler_base.h"
namespace device {
class COMPONENT_EXPORT(DEVICE_FIDO) BioEnrollmentHandler
: public FidoRequestHandlerBase,
public BioEnroller::Delegate {
public:
enum class Error {
kAuthenticatorRemoved,
kAuthenticatorResponseInvalid,
kSoftPINBlock,
kHardPINBlock,
kNoPINSet,
kAuthenticatorMissingBioEnrollment,
kForcePINChange,
};
struct COMPONENT_EXPORT(DEVICE_FIDO) SensorInfo {
SensorInfo();
SensorInfo(const SensorInfo&) = delete;
SensorInfo(SensorInfo&&);
SensorInfo& operator=(const SensorInfo&) = delete;
SensorInfo& operator=(SensorInfo&&);
std::optional<uint8_t> max_samples_for_enroll;
uint32_t max_template_friendly_name;
};
using TemplateId = std::vector<uint8_t>;
using ReadyCallback = base::OnceCallback<void(SensorInfo)>;
using ErrorCallback = base::OnceCallback<void(Error)>;
using GetPINCallback =
base::RepeatingCallback<void(uint32_t min_pin_length,
int64_t retries,
base::OnceCallback<void(std::string)>)>;
using StatusCallback = base::OnceCallback<void(CtapDeviceResponseCode)>;
using EnumerationCallback = base::OnceCallback<void(
CtapDeviceResponseCode,
std::optional<std::map<TemplateId, std::string>>)>;
using SampleCallback =
base::RepeatingCallback<void(BioEnrollmentSampleStatus, uint8_t)>;
using EnrollmentCallback =
base::OnceCallback<void(CtapDeviceResponseCode, TemplateId)>;
BioEnrollmentHandler(
const base::flat_set<FidoTransportProtocol>& supported_transports,
ReadyCallback ready_callback,
ErrorCallback error_callback,
GetPINCallback get_pin_callback,
FidoDiscoveryFactory* factory);
~BioEnrollmentHandler() override;
BioEnrollmentHandler(const BioEnrollmentHandler&) = delete;
BioEnrollmentHandler(BioEnrollmentHandler&&) = delete;
void EnrollTemplate(SampleCallback sample_callback,
EnrollmentCallback enrollment_callback);
void CancelEnrollment();
void EnumerateTemplates(EnumerationCallback);
void RenameTemplate(std::vector<uint8_t> template_id,
std::string name,
StatusCallback);
void DeleteTemplate(std::vector<uint8_t> template_id, StatusCallback);
private:
enum class State {
kWaitingForTouch,
kGettingRetries,
kWaitingForPIN,
kGettingPINToken,
kGettingSensorInfo,
kReady,
kEnrolling,
kCancellingEnrollment,
kEnumerating,
kRenaming,
kDeleting,
kFinished,
};
void DispatchRequest(FidoAuthenticator*) override;
void AuthenticatorRemoved(FidoDiscoveryBase*, FidoAuthenticator*) override;
void OnSampleCollected(BioEnrollmentSampleStatus status,
int samples_remaining) override;
void OnEnrollmentDone(
std::optional<std::vector<uint8_t>> template_id) override;
void OnEnrollmentError(CtapDeviceResponseCode status) override;
void OnTouch(FidoAuthenticator* authenticator);
void OnRetriesResponse(CtapDeviceResponseCode,
std::optional<pin::RetriesResponse>);
void OnHavePIN(std::string pin);
void OnHavePINToken(CtapDeviceResponseCode,
std::optional<pin::TokenResponse>);
void OnGetSensorInfo(CtapDeviceResponseCode,
std::optional<BioEnrollmentResponse>);
void OnEnumerateTemplates(EnumerationCallback,
CtapDeviceResponseCode,
std::optional<BioEnrollmentResponse>);
void OnRenameTemplate(StatusCallback,
CtapDeviceResponseCode,
std::optional<BioEnrollmentResponse>);
void OnDeleteTemplate(StatusCallback,
CtapDeviceResponseCode,
std::optional<BioEnrollmentResponse>);
void RunErrorCallback(Error error);
SEQUENCE_CHECKER(sequence_checker_);
State state_ = State::kWaitingForTouch;
raw_ptr<FidoAuthenticator> authenticator_ = nullptr;
std::unique_ptr<BioEnroller> bio_enroller_;
ReadyCallback ready_callback_;
ErrorCallback error_callback_;
GetPINCallback get_pin_callback_;
EnrollmentCallback enrollment_callback_;
SampleCallback sample_callback_;
std::optional<pin::TokenResponse> pin_token_response_;
base::WeakPtrFactory<BioEnrollmentHandler> weak_factory_{this};
};
}
#endif