// Copyright 2018 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.

#include "chrome/browser/webauthn/authenticator_request_dialog_model.h"

#include <iterator>
#include <utility>

#include "base/bind.h"
#include "base/stl_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "build/build_config.h"
#include "device/fido/fido_authenticator.h"

namespace {

bool ShouldShowBlePairingUI(
    bool previously_paired_with_bluetooth_authenticator,
    bool pair_with_new_device_for_bluetooth_low_energy) {
  if (pair_with_new_device_for_bluetooth_low_energy)
    return true;

  return !previously_paired_with_bluetooth_authenticator;
}

// Attempts to auto-select the most likely transport that will be used to
// service this request, or returns base::nullopt if unsure.
base::Optional<device::FidoTransportProtocol> SelectMostLikelyTransport(
    const device::FidoRequestHandlerBase::TransportAvailabilityInfo&
        transport_availability,
    base::Optional<device::FidoTransportProtocol> last_used_transport) {
  base::flat_set<AuthenticatorTransport> candidate_transports(
      transport_availability.available_transports);

  // As an exception, we can tell in advance if using Touch Id will succeed. If
  // yes, always auto-select that transport over all other considerations for
  // GetAssertion operations; and de-select it if it will not work.
  if (transport_availability.request_type ==
          device::FidoRequestHandlerBase::RequestType::kGetAssertion &&
      base::ContainsKey(candidate_transports,
                        device::FidoTransportProtocol::kInternal)) {
    // For GetAssertion requests, auto advance to Touch ID if the keychain
    // contains one of the allowedCredentials.
    if (transport_availability.has_recognized_mac_touch_id_credential)
      return device::FidoTransportProtocol::kInternal;
  }

  // If caBLE is listed as one of the allowed transports, it indicates that the
  // RP has bothered to supply the |cable_extension|. Respect that and always
  // select caBLE in that case for GetAssertion operations.
  if (transport_availability.request_type ==
          device::FidoRequestHandlerBase::RequestType::kGetAssertion &&
      base::ContainsKey(
          candidate_transports,
          AuthenticatorTransport::kCloudAssistedBluetoothLowEnergy)) {
    return AuthenticatorTransport::kCloudAssistedBluetoothLowEnergy;
  }

  // Otherwise, for GetAssertion calls, if the |last_used_transport| is
  // available, use that. Unless the preference is Touch ID, because Touch ID
  // at this point is guaranteed to not have the credential and would go
  // straight to its special error screen.
  if (transport_availability.request_type ==
          device::FidoRequestHandlerBase::RequestType::kGetAssertion &&
      last_used_transport &&
      base::ContainsKey(candidate_transports, *last_used_transport) &&
      *last_used_transport != device::FidoTransportProtocol::kInternal) {
    return *last_used_transport;
  }

  // Finally, if there is only one transport available we can use, select that,
  // instead of showing a transport selection screen with only a single item.
  if (candidate_transports.size() == 1) {
    return *candidate_transports.begin();
  }

  return base::nullopt;
}

}  // namespace

AuthenticatorRequestDialogModel::AuthenticatorRequestDialogModel()
    : weak_factory_(this) {}

AuthenticatorRequestDialogModel::~AuthenticatorRequestDialogModel() {
  for (auto& observer : observers_)
    observer.OnModelDestroyed();
}

void AuthenticatorRequestDialogModel::SetCurrentStep(Step step) {
  current_step_ = step;
  for (auto& observer : observers_)
    observer.OnStepTransition();
}

void AuthenticatorRequestDialogModel::HideDialog() {
  SetCurrentStep(Step::kNotStarted);
}

void AuthenticatorRequestDialogModel::StartFlow(
    TransportAvailabilityInfo transport_availability,
    base::Optional<device::FidoTransportProtocol> last_used_transport,
    const base::ListValue* previously_paired_bluetooth_device_list) {
  DCHECK_EQ(current_step(), Step::kNotStarted);

  transport_availability_ = std::move(transport_availability);
  last_used_transport_ = last_used_transport;
  for (const auto transport : transport_availability_.available_transports) {
    available_transports_.emplace_back(transport);
  }

  previously_paired_with_bluetooth_authenticator_ =
      previously_paired_bluetooth_device_list &&
      !previously_paired_bluetooth_device_list->GetList().empty();

  StartGuidedFlowForMostLikelyTransportOrShowTransportSelection();
}

void AuthenticatorRequestDialogModel::
    StartGuidedFlowForMostLikelyTransportOrShowTransportSelection() {
  DCHECK(current_step() == Step::kWelcomeScreen ||
         current_step() == Step::kNotStarted);

  // If no authenticator other than the one for the native Windows API is
  // available, don't show Chrome UI but proceed straight to the native
  // Windows UI.
  if (transport_availability_.has_win_native_api_authenticator &&
      transport_availability_.available_transports.empty()) {
    HideDialogAndDispatchToNativeWindowsApi();
    return;
  }

  auto most_likely_transport =
      SelectMostLikelyTransport(transport_availability_, last_used_transport_);
  if (most_likely_transport) {
    StartGuidedFlowForTransport(*most_likely_transport);
  } else if (!transport_availability_.available_transports.empty()) {
    DCHECK_GE(transport_availability_.available_transports.size(), 2u);
    SetCurrentStep(Step::kTransportSelection);
  } else {
    SetCurrentStep(Step::kErrorNoAvailableTransports);
  }
}

void AuthenticatorRequestDialogModel::StartGuidedFlowForTransport(
    AuthenticatorTransport transport,
    bool pair_with_new_device_for_bluetooth_low_energy) {
  DCHECK(current_step() == Step::kTransportSelection ||
         current_step() == Step::kWelcomeScreen ||
         current_step() == Step::kUsbInsertAndActivate ||
         current_step() == Step::kBleActivate ||
         current_step() == Step::kCableActivate ||
         current_step() == Step::kNotStarted);
  switch (transport) {
    case AuthenticatorTransport::kUsbHumanInterfaceDevice:
      SetCurrentStep(Step::kUsbInsertAndActivate);
      break;
    case AuthenticatorTransport::kNearFieldCommunication:
      SetCurrentStep(Step::kTransportSelection);
      break;
    case AuthenticatorTransport::kInternal:
      StartTouchIdFlow();
      break;
    case AuthenticatorTransport::kBluetoothLowEnergy: {
      Step next_step = ShouldShowBlePairingUI(
                           previously_paired_with_bluetooth_authenticator_,
                           pair_with_new_device_for_bluetooth_low_energy)
                           ? Step::kBlePairingBegin
                           : Step::kBleActivate;
      EnsureBleAdapterIsPoweredBeforeContinuingWithStep(next_step);
      break;
    }
    case AuthenticatorTransport::kCloudAssistedBluetoothLowEnergy:
      EnsureBleAdapterIsPoweredBeforeContinuingWithStep(Step::kCableActivate);
      break;
    default:
      break;
  }
}

void AuthenticatorRequestDialogModel::
    HideDialogAndDispatchToNativeWindowsApi() {
  if (!transport_availability()->has_win_native_api_authenticator ||
      transport_availability()->win_native_api_authenticator_id.empty()) {
    NOTREACHED();
    SetCurrentStep(Step::kClosed);
    return;
  }

  // There is no AuthenticatorReference for the Windows authenticator,
  // hence directly call DispatchRequestAsyncInternal here.
  DispatchRequestAsyncInternal(
      transport_availability()->win_native_api_authenticator_id);

  HideDialog();
}

void AuthenticatorRequestDialogModel::
    EnsureBleAdapterIsPoweredBeforeContinuingWithStep(Step next_step) {
  DCHECK(current_step() == Step::kTransportSelection ||
         current_step() == Step::kWelcomeScreen ||
         current_step() == Step::kUsbInsertAndActivate ||
         current_step() == Step::kBleActivate ||
         current_step() == Step::kCableActivate ||
         current_step() == Step::kNotStarted);
  if (ble_adapter_is_powered()) {
    SetCurrentStep(next_step);
  } else {
    next_step_once_ble_powered_ = next_step;
    if (transport_availability()->can_power_on_ble_adapter)
      SetCurrentStep(Step::kBlePowerOnAutomatic);
    else
      SetCurrentStep(Step::kBlePowerOnManual);
  }
}

void AuthenticatorRequestDialogModel::ContinueWithFlowAfterBleAdapterPowered() {
  DCHECK(current_step() == Step::kBlePowerOnManual ||
         current_step() == Step::kBlePowerOnAutomatic);
  DCHECK(ble_adapter_is_powered());
  DCHECK(next_step_once_ble_powered_.has_value());

  SetCurrentStep(*next_step_once_ble_powered_);
}

void AuthenticatorRequestDialogModel::PowerOnBleAdapter() {
  DCHECK_EQ(current_step(), Step::kBlePowerOnAutomatic);
  if (!bluetooth_adapter_power_on_callback_)
    return;

  bluetooth_adapter_power_on_callback_.Run();
}

void AuthenticatorRequestDialogModel::StartBleDiscovery() {
  DCHECK_EQ(current_step(), Step::kBlePairingBegin);
}

void AuthenticatorRequestDialogModel::InitiatePairingDevice(
    base::StringPiece authenticator_id) {
  DCHECK_EQ(current_step(), Step::kBleDeviceSelection);
  auto* selected_authenticator =
      saved_authenticators_.GetAuthenticator(authenticator_id);
  DCHECK(selected_authenticator);
  selected_authenticator_id_ = authenticator_id.as_string();

// For MacOS, Bluetooth pin pairing is done via system native UI, which is
// triggered by a write attempt to GATT characteristic. Thus, simply resume
// with WebAuthn request for MacOS.
#if defined(OS_MACOSX)
  SetCurrentStep(Step::kBleVerifying);
  DispatchRequestAsync(selected_authenticator);
#else
  SetCurrentStep(Step::kBlePinEntry);
#endif
}

void AuthenticatorRequestDialogModel::FinishPairingWithPin(
    const base::string16& pin) {
  DCHECK_EQ(current_step(), Step::kBlePinEntry);
  DCHECK(selected_authenticator_id_);
  const auto* selected_authenticator =
      saved_authenticators_.GetAuthenticator(*selected_authenticator_id_);
  if (!selected_authenticator) {
    // TODO(hongjunchoi): Implement an error screen for error encountered when
    // pairing.
    SetCurrentStep(Step::kBleDeviceSelection);
    return;
  }

  DCHECK_EQ(device::FidoTransportProtocol::kBluetoothLowEnergy,
            selected_authenticator->transport());
  ble_pairing_callback_.Run(
      *selected_authenticator_id_, base::UTF16ToUTF8(pin),
      base::BindOnce(&AuthenticatorRequestDialogModel::OnPairingSuccess,
                     weak_factory_.GetWeakPtr()),
      base::BindOnce(&AuthenticatorRequestDialogModel::OnPairingFailure,
                     weak_factory_.GetWeakPtr()));
  SetCurrentStep(Step::kBleVerifying);
}

void AuthenticatorRequestDialogModel::OnPairingSuccess() {
  DCHECK_EQ(current_step(), Step::kBleVerifying);
  DCHECK(selected_authenticator_id_);
  auto* authenticator =
      saved_authenticators_.GetAuthenticator(*selected_authenticator_id_);
  if (!authenticator)
    return;

  authenticator->SetIsPaired(true /* is_paired */);
  DCHECK(ble_device_paired_callback_);
  ble_device_paired_callback_.Run(*selected_authenticator_id_);

  DispatchRequestAsync(authenticator);
}

void AuthenticatorRequestDialogModel::OnPairingFailure() {
  DCHECK_EQ(current_step(), Step::kBleVerifying);
  selected_authenticator_id_.reset();
  SetCurrentStep(Step::kBleDeviceSelection);
}

void AuthenticatorRequestDialogModel::TryUsbDevice() {
  DCHECK_EQ(current_step(), Step::kUsbInsertAndActivate);
}

void AuthenticatorRequestDialogModel::StartTouchIdFlow() {
  // Never try Touch ID if the request is known in advance to fail. Proceed to
  // a special error screen instead.
  if (transport_availability_.request_type ==
          device::FidoRequestHandlerBase::RequestType::kGetAssertion &&
      !transport_availability_.has_recognized_mac_touch_id_credential) {
    SetCurrentStep(Step::kErrorInternalUnrecognized);
    return;
  }

  if (transport_availability_.request_type ==
          device::FidoRequestHandlerBase::RequestType::kMakeCredential &&
      incognito_mode_) {
    SetCurrentStep(Step::kTouchIdIncognitoSpeedBump);
    return;
  }

  HideDialogAndTryTouchId();
}

void AuthenticatorRequestDialogModel::HideDialogAndTryTouchId() {
  HideDialog();

  auto& authenticators = saved_authenticators_.authenticator_list();
  auto touch_id_authenticator_it =
      std::find_if(authenticators.begin(), authenticators.end(),
                   [](const auto& authenticator) {
                     return authenticator.transport() ==
                            device::FidoTransportProtocol::kInternal;
                   });

  if (touch_id_authenticator_it == authenticators.end()) {
    return;
  }

  DispatchRequestAsync(&*touch_id_authenticator_it);
}

void AuthenticatorRequestDialogModel::Cancel() {
  if (is_request_complete()) {
    SetCurrentStep(Step::kClosed);
  }

  for (auto& observer : observers_)
    observer.OnCancelRequest();
}

void AuthenticatorRequestDialogModel::Back() {
  SetCurrentStep(Step::kTransportSelection);
}

void AuthenticatorRequestDialogModel::OnSheetModelDidChange() {
  for (auto& observer : observers_)
    observer.OnSheetModelChanged();
}

void AuthenticatorRequestDialogModel::AddObserver(Observer* observer) {
  observers_.AddObserver(observer);
}

void AuthenticatorRequestDialogModel::RemoveObserver(Observer* observer) {
  observers_.RemoveObserver(observer);
}

void AuthenticatorRequestDialogModel::OnRequestComplete() {
  SetCurrentStep(Step::kClosed);
}

void AuthenticatorRequestDialogModel::OnRequestTimeout() {
  // The request may time out while the UI shows a different error.
  if (!is_request_complete())
    SetCurrentStep(Step::kTimedOut);
}

void AuthenticatorRequestDialogModel::OnActivatedKeyNotRegistered() {
  DCHECK(!is_request_complete());
  SetCurrentStep(Step::kKeyNotRegistered);
}

void AuthenticatorRequestDialogModel::OnActivatedKeyAlreadyRegistered() {
  DCHECK(!is_request_complete());
  SetCurrentStep(Step::kKeyAlreadyRegistered);
}

void AuthenticatorRequestDialogModel::OnSoftPINBlock() {
  SetCurrentStep(Step::kClientPinErrorSoftBlock);
}

void AuthenticatorRequestDialogModel::OnHardPINBlock() {
  SetCurrentStep(Step::kClientPinErrorHardBlock);
}

void AuthenticatorRequestDialogModel::OnAuthenticatorRemovedDuringPINEntry() {
  SetCurrentStep(Step::kClientPinErrorAuthenticatorRemoved);
}

void AuthenticatorRequestDialogModel::OnAuthenticatorMissingResidentKeys() {
  SetCurrentStep(Step::kMissingResidentKeys);
}

void AuthenticatorRequestDialogModel::OnAuthenticatorMissingUserVerification() {
  SetCurrentStep(Step::kMissingUserVerification);
}

void AuthenticatorRequestDialogModel::OnBluetoothPoweredStateChanged(
    bool powered) {
  transport_availability_.is_ble_powered = powered;

  for (auto& observer : observers_)
    observer.OnBluetoothPoweredStateChanged();

  // For the manual flow, the user has to click the "next" button explicitly.
  if (current_step() == Step::kBlePowerOnAutomatic)
    ContinueWithFlowAfterBleAdapterPowered();
}

void AuthenticatorRequestDialogModel::SetRequestCallback(
    RequestCallback request_callback) {
  request_callback_ = request_callback;
}

void AuthenticatorRequestDialogModel::SetBlePairingCallback(
    BlePairingCallback ble_pairing_callback) {
  ble_pairing_callback_ = ble_pairing_callback;
}

void AuthenticatorRequestDialogModel::SetBluetoothAdapterPowerOnCallback(
    base::RepeatingClosure bluetooth_adapter_power_on_callback) {
  bluetooth_adapter_power_on_callback_ = bluetooth_adapter_power_on_callback;
}

void AuthenticatorRequestDialogModel::UpdateAuthenticatorReferenceId(
    base::StringPiece old_authenticator_id,
    std::string new_authenticator_id) {
  // Bluetooth authenticator address may be changed during pairing process after
  // the user chose device to pair during device selection UI. Thus, change
  // |selected_authenticator_id_| as well.
  if (selected_authenticator_id_ &&
      *selected_authenticator_id_ == old_authenticator_id)
    selected_authenticator_id_ = new_authenticator_id;

  saved_authenticators_.ChangeAuthenticatorId(old_authenticator_id,
                                              std::move(new_authenticator_id));
}

void AuthenticatorRequestDialogModel::SetBleDevicePairedCallback(
    BleDevicePairedCallback ble_device_paired_callback) {
  ble_device_paired_callback_ = std::move(ble_device_paired_callback);
}

void AuthenticatorRequestDialogModel::SetPINCallback(
    base::OnceCallback<void(std::string)> pin_callback) {
  pin_callback_ = std::move(pin_callback);
}

void AuthenticatorRequestDialogModel::OnHavePIN(const std::string& pin) {
  if (!pin_callback_) {
    // Protect against the view submitting a PIN more than once without
    // receiving a matching response first. |SetPINCallback| is called again if
    // the user needs to be prompted for a retry.
    return;
  }
  std::move(pin_callback_).Run(pin);
  has_attempted_pin_entry_ = true;
}

void AuthenticatorRequestDialogModel::OnAttestationPermissionResponse(
    bool attestation_permission_granted) {
  if (!attestation_callback_) {
    return;
  }
  std::move(attestation_callback_).Run(attestation_permission_granted);
}

void AuthenticatorRequestDialogModel::AddAuthenticator(
    const device::FidoAuthenticator& authenticator) {
  if (!authenticator.AuthenticatorTransport()) {
#if defined(OS_WIN)
    DCHECK(authenticator.IsWinNativeApiAuthenticator());
#endif  // defined(OS_WIN)
    return;
  }

  AuthenticatorReference authenticator_reference(
      authenticator.GetId(), authenticator.GetDisplayName(),
      *authenticator.AuthenticatorTransport(), authenticator.IsInPairingMode(),
      authenticator.IsPaired());

  if (authenticator_reference.is_paired() &&
      authenticator_reference.transport() ==
          AuthenticatorTransport::kBluetoothLowEnergy) {
    DispatchRequestAsync(&authenticator_reference);
  }
  saved_authenticators_.AddAuthenticator(std::move(authenticator_reference));
}

void AuthenticatorRequestDialogModel::RemoveAuthenticator(
    base::StringPiece authenticator_id) {
  saved_authenticators_.RemoveAuthenticator(authenticator_id);
}

void AuthenticatorRequestDialogModel::DispatchRequestAsync(
    AuthenticatorReference* authenticator) {
  // Dispatching to the same authenticator twice may result in unexpected
  // behavior.
  if (authenticator->dispatched()) {
    return;
  }

  DispatchRequestAsyncInternal(authenticator->authenticator_id());
  authenticator->SetDispatched(true);
}

void AuthenticatorRequestDialogModel::DispatchRequestAsyncInternal(
    const std::string& authenticator_id) {
  if (!request_callback_)
    return;

  base::SequencedTaskRunnerHandle::Get()->PostTask(
      FROM_HERE, base::BindOnce(request_callback_, authenticator_id));
}

void AuthenticatorRequestDialogModel::UpdateAuthenticatorReferencePairingMode(
    base::StringPiece authenticator_id,
    bool is_in_pairing_mode) {
  saved_authenticators_.ChangeAuthenticatorPairingMode(authenticator_id,
                                                       is_in_pairing_mode);
}

// SelectAccount is called to trigger an account selection dialog.
void AuthenticatorRequestDialogModel::SelectAccount(
    std::vector<device::AuthenticatorGetAssertionResponse> responses,
    base::OnceCallback<void(device::AuthenticatorGetAssertionResponse)>
        callback) {
  responses_ = std::move(responses);
  selection_callback_ = std::move(callback);
  SetCurrentStep(Step::kSelectAccount);
}

void AuthenticatorRequestDialogModel::OnAccountSelected(size_t index) {
  if (!selection_callback_) {
    // It's possible that the user could activate the dialog more than once
    // before the Webauthn request is completed and its torn down.
    return;
  }

  auto selected = std::move(responses_[index]);
  responses_.clear();
  std::move(selection_callback_).Run(std::move(selected));
}

void AuthenticatorRequestDialogModel::SetSelectedAuthenticatorForTesting(
    AuthenticatorReference test_authenticator) {
  selected_authenticator_id_ = test_authenticator.authenticator_id();
  saved_authenticators_.AddAuthenticator(std::move(test_authenticator));
}

void AuthenticatorRequestDialogModel::CollectPIN(
    base::Optional<int> attempts,
    base::OnceCallback<void(std::string)> provide_pin_cb) {
  pin_callback_ = std::move(provide_pin_cb);
  if (attempts) {
    pin_attempts_ = attempts;
    SetCurrentStep(Step::kClientPinEntry);
  } else {
    SetCurrentStep(Step::kClientPinSetup);
  }
}

void AuthenticatorRequestDialogModel::RequestAttestationPermission(
    base::OnceCallback<void(bool)> callback) {
  DCHECK(current_step_ != Step::kClosed);
  attestation_callback_ = std::move(callback);
  SetCurrentStep(Step::kAttestationPermissionRequest);
}
