#include "device/fido/bio/enroller.h"
#include <utility>
#include "base/functional/bind.h"
#include "device/fido/fido_authenticator.h"
namespace device {
BioEnroller::BioEnroller(Delegate* delegate,
FidoAuthenticator* authenticator,
pin::TokenResponse token)
: delegate_(delegate), authenticator_(authenticator), token_(token) {
authenticator_->BioEnrollFingerprint(
token_, std::nullopt,
base::BindOnce(&BioEnroller::OnEnrollResponse,
weak_factory_.GetWeakPtr()));
}
BioEnroller::~BioEnroller() = default;
void BioEnroller::Cancel() {
if (state_ == State::kDone) {
return;
}
state_ = State::kCancelled;
authenticator_->Cancel();
}
void BioEnroller::FinishWithError(CtapDeviceResponseCode status) {
state_ = State::kDone;
delegate_->OnEnrollmentError(status);
}
void BioEnroller::FinishSuccessfully(
std::optional<std::vector<uint8_t>> template_id) {
state_ = State::kDone;
delegate_->OnEnrollmentDone(std::move(template_id));
}
void BioEnroller::OnEnrollResponse(
CtapDeviceResponseCode status,
std::optional<BioEnrollmentResponse> response) {
DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker_);
if (state_ == State::kCancelled) {
if (status == CtapDeviceResponseCode::kSuccess &&
response->remaining_samples == 0) {
FinishSuccessfully(std::move(template_id_));
return;
}
authenticator_->BioEnrollCancel(base::BindOnce(
&BioEnroller::OnEnrollCancelled, weak_factory_.GetWeakPtr()));
return;
}
DCHECK_EQ(state_, State::kInProgress);
if (status != CtapDeviceResponseCode::kSuccess) {
FinishWithError(status);
return;
}
if (!response || !response->last_status || !response->remaining_samples ||
response->remaining_samples < 0) {
FinishWithError(CtapDeviceResponseCode::kCtap2ErrInvalidCBOR);
return;
}
if (!template_id_) {
if (!response->template_id) {
FinishWithError(CtapDeviceResponseCode::kCtap2ErrInvalidCBOR);
return;
}
template_id_ = *response->template_id;
}
if (response->last_status != BioEnrollmentSampleStatus::kNoUserActivity) {
delegate_->OnSampleCollected(*response->last_status,
*response->remaining_samples);
}
if (response->remaining_samples == 0) {
FinishSuccessfully(std::move(template_id_));
return;
}
authenticator_->BioEnrollFingerprint(
token_, template_id_,
base::BindOnce(&BioEnroller::OnEnrollResponse,
weak_factory_.GetWeakPtr()));
}
void BioEnroller::OnEnrollCancelled(
CtapDeviceResponseCode status,
std::optional<BioEnrollmentResponse> response) {
DCHECK_EQ(state_, State::kCancelled);
FinishSuccessfully(std::nullopt);
}
}