// Copyright 2014 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/chromeos/login/easy_unlock/easy_unlock_service_regular.h"

#include <stdint.h>

#include <utility>

#include "apps/app_lifetime_monitor_factory.h"
#include "base/base64url.h"
#include "base/bind.h"
#include "base/command_line.h"
#include "base/json/json_string_value_serializer.h"
#include "base/linux_util.h"
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
#include "base/system/sys_info.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/default_clock.h"
#include "base/values.h"
#include "build/build_config.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/login/easy_unlock/chrome_proximity_auth_client.h"
#include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_key_manager.h"
#include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_key_names.h"
#include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_notification_controller.h"
#include "chrome/browser/chromeos/login/session/user_session_manager.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "chrome/browser/gcm/gcm_profile_service_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/signin/identity_manager_factory.h"
#include "chrome/browser/ui/webui/chromeos/multidevice_setup/multidevice_setup_dialog.h"
#include "chrome/common/chrome_features.h"
#include "chrome/common/extensions/extension_constants.h"
#include "chrome/common/pref_names.h"
#include "chromeos/chromeos_features.h"
#include "chromeos/components/proximity_auth/logging/logging.h"
#include "chromeos/components/proximity_auth/proximity_auth_pref_names.h"
#include "chromeos/components/proximity_auth/proximity_auth_profile_pref_manager.h"
#include "chromeos/components/proximity_auth/proximity_auth_system.h"
#include "chromeos/components/proximity_auth/screenlock_bridge.h"
#include "chromeos/components/proximity_auth/smart_lock_metrics_recorder.h"
#include "chromeos/components/proximity_auth/switches.h"
#include "chromeos/services/device_sync/cryptauth_enrollment_manager.h"
#include "chromeos/services/device_sync/cryptauth_gcm_manager_impl.h"
#include "chromeos/services/device_sync/remote_device_loader.h"
#include "components/gcm_driver/gcm_profile_service.h"
#include "components/pref_registry/pref_registry_syncable.h"
#include "components/prefs/pref_service.h"
#include "components/prefs/scoped_user_pref_update.h"
#include "components/translate/core/browser/translate_download_manager.h"
#include "components/user_manager/user_manager.h"
#include "components/version_info/version_info.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/content_switches.h"
#include "extensions/browser/event_router.h"
#include "extensions/common/constants.h"
#include "google_apis/gaia/gaia_auth_util.h"
#include "services/identity/public/cpp/identity_manager.h"

namespace chromeos {

namespace {

// Key name of the local device permit record dictonary in kEasyUnlockPairing.
const char kKeyPermitAccess[] = "permitAccess";

// Key name of the remote device list in kEasyUnlockPairing.
const char kKeyDevices[] = "devices";

enum class SmartLockToggleFeature { DISABLE = false, ENABLE = true };

// The result of a SmartLock operation.
enum class SmartLockResult { FAILURE = false, SUCCESS = true };

enum class SmartLockEnabledState {
  ENABLED = 0,
  DISABLED = 1,
  UNSET = 2,
  COUNT
};

void LogSmartLockEnabledState(SmartLockEnabledState state) {
  UMA_HISTOGRAM_ENUMERATION("SmartLock.EnabledState", state,
                            SmartLockEnabledState::COUNT);
}

}  // namespace

EasyUnlockServiceRegular::EasyUnlockServiceRegular(
    Profile* profile,
    secure_channel::SecureChannelClient* secure_channel_client,
    device_sync::DeviceSyncClient* device_sync_client,
    multidevice_setup::MultiDeviceSetupClient* multidevice_setup_client)
    : EasyUnlockServiceRegular(
          profile,
          secure_channel_client,
          std::make_unique<EasyUnlockNotificationController>(profile),
          device_sync_client,
          multidevice_setup_client) {}

EasyUnlockServiceRegular::EasyUnlockServiceRegular(
    Profile* profile,
    secure_channel::SecureChannelClient* secure_channel_client,
    std::unique_ptr<EasyUnlockNotificationController> notification_controller,
    device_sync::DeviceSyncClient* device_sync_client,
    multidevice_setup::MultiDeviceSetupClient* multidevice_setup_client)
    : EasyUnlockService(profile, secure_channel_client),
      lock_screen_last_shown_timestamp_(base::TimeTicks::Now()),
      deferring_device_load_(false),
      notification_controller_(std::move(notification_controller)),
      device_sync_client_(device_sync_client),
      multidevice_setup_client_(multidevice_setup_client),
      shown_pairing_changed_notification_(false),
      weak_ptr_factory_(this) {
  // If |device_sync_client_| is not ready yet, wait for it to call back on
  // OnReady().
  if (device_sync_client_->is_ready())
    OnReady();

  device_sync_client_->AddObserver(this);

  OnFeatureStatesChanged(multidevice_setup_client_->GetFeatureStates());

  multidevice_setup_client_->AddObserver(this);
}

EasyUnlockServiceRegular::~EasyUnlockServiceRegular() = default;

// TODO(jhawkins): This method with |has_unlock_keys| == true is the only signal
// that SmartLock setup has completed successfully. Make this signal more
// explicit.
void EasyUnlockServiceRegular::LoadRemoteDevices() {
  if (!device_sync_client_->is_ready()) {
    // OnEnrollmentFinished() or OnNewDevicesSynced() will call back on this
    // method once |device_sync_client_| is ready.
    PA_LOG(VERBOSE) << "DeviceSyncClient is not ready yet, delaying "
                       "UseLoadedRemoteDevices().";
    return;
  }

  // TODO(crbug.com/894585): Remove this legacy special case after M71.
  bool is_in_legacy_host_mode = IsInLegacyHostMode();
  pref_manager_->SetIsInLegacyHostMode(is_in_legacy_host_mode);

  bool is_in_valid_legacy_host_state =
      is_in_legacy_host_mode &&
      feature_state_ ==
          multidevice_setup::mojom::FeatureState::kUnavailableNoVerifiedHost;
  if (feature_state_ !=
          multidevice_setup::mojom::FeatureState::kEnabledByUser &&
      !is_in_valid_legacy_host_state) {
    // OnFeatureStatesChanged() will call back on this method when feature state
    // changes.
    PA_LOG(VERBOSE) << "Smart Lock is disabled; aborting.";
    SetProximityAuthDevices(GetAccountId(), multidevice::RemoteDeviceRefList(),
                            base::nullopt /* local_device */);
    return;
  }

  bool has_unlock_keys = !GetUnlockKeys().empty();

  // TODO(jhawkins): The enabled pref should not be tied to whether unlock keys
  // exist; instead, both of these variables should be used to determine
  // IsEnabled().
  pref_manager_->SetIsEasyUnlockEnabled(has_unlock_keys);
  if (has_unlock_keys) {
    // If |has_unlock_keys| is true, then the user must have successfully
    // completed setup. Track that the IsEasyUnlockEnabled pref is actively set
    // by the user, as opposed to passively being set to disabled (the default
    // state).
    pref_manager_->SetEasyUnlockEnabledStateSet();
    LogSmartLockEnabledState(SmartLockEnabledState::ENABLED);
  } else {
    SetProximityAuthDevices(GetAccountId(), multidevice::RemoteDeviceRefList(),
                            base::nullopt /* local_device */);

    if (pref_manager_->IsEasyUnlockEnabledStateSet()) {
      LogSmartLockEnabledState(SmartLockEnabledState::DISABLED);
    } else {
      LogSmartLockEnabledState(SmartLockEnabledState::UNSET);
    }
    return;
  }

  // This code path may be hit by:
  //   1. New devices were synced on the lock screen.
  //   2. The service was initialized while the login screen is still up.
  if (proximity_auth::ScreenlockBridge::Get()->IsLocked()) {
    PA_LOG(VERBOSE) << "Deferring device load until screen is unlocked.";
    deferring_device_load_ = true;
    return;
  }

  UseLoadedRemoteDevices(GetUnlockKeys());
}

void EasyUnlockServiceRegular::UseLoadedRemoteDevices(
    const multidevice::RemoteDeviceRefList& remote_devices) {
  // When EasyUnlock is enabled, only one EasyUnlock host should exist.
  DCHECK(remote_devices.size() == 1u);

  SetProximityAuthDevices(GetAccountId(), remote_devices,
                          device_sync_client_->GetLocalDeviceMetadata());

  // We need to store a copy of |local_and_remote_devices| in the TPM, so it can
  // be retrieved on the sign-in screen when a user session has not been started
  // yet. This expects a final size of 2 (the one remote device, and the local
  // device).
  // TODO(crbug.com/856380): For historical reasons, the local and remote device
  // are persisted together in a list. This is awkward and hacky; they should
  // be persisted in a dictionary.
  multidevice::RemoteDeviceRefList local_and_remote_devices;
  local_and_remote_devices.push_back(remote_devices[0]);
  local_and_remote_devices.push_back(
      *device_sync_client_->GetLocalDeviceMetadata());

  std::unique_ptr<base::ListValue> device_list(new base::ListValue());
  for (const auto& device : local_and_remote_devices) {
    std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
    std::string b64_public_key, b64_psk;
    base::Base64UrlEncode(device.public_key(),
                          base::Base64UrlEncodePolicy::INCLUDE_PADDING,
                          &b64_public_key);
    base::Base64UrlEncode(device.persistent_symmetric_key(),
                          base::Base64UrlEncodePolicy::INCLUDE_PADDING,
                          &b64_psk);

    dict->SetString(key_names::kKeyPsk, b64_psk);

    // TODO(jhawkins): Remove the bluetoothAddress field from this proto.
    dict->SetString(key_names::kKeyBluetoothAddress, std::string());

    dict->SetString(
        key_names::kKeyPermitPermitId,
        base::StringPrintf(
            key_names::kPermitPermitIdFormat,
            gaia::CanonicalizeEmail(GetAccountId().GetUserEmail()).c_str()));

    dict->SetString(key_names::kKeyPermitId, b64_public_key);
    dict->SetString(key_names::kKeyPermitType, key_names::kPermitTypeLicence);
    dict->SetString(key_names::kKeyPermitData, b64_public_key);

    std::unique_ptr<base::ListValue> beacon_seed_list(new base::ListValue());
    for (const auto& beacon_seed : device.beacon_seeds()) {
      std::string b64_beacon_seed;
      base::Base64UrlEncode(
          multidevice::ToCryptAuthSeed(beacon_seed).SerializeAsString(),
          base::Base64UrlEncodePolicy::INCLUDE_PADDING, &b64_beacon_seed);
      beacon_seed_list->AppendString(b64_beacon_seed);
    }

    std::string serialized_beacon_seeds;
    JSONStringValueSerializer serializer(&serialized_beacon_seeds);
    serializer.Serialize(*beacon_seed_list);
    dict->SetString(key_names::kKeySerializedBeaconSeeds,
                    serialized_beacon_seeds);

    // This differentiates the local device from the remote device.
    bool unlock_key = device.GetSoftwareFeatureState(
                          multidevice::SoftwareFeature::kSmartLockHost) ==
                      multidevice::SoftwareFeatureState::kEnabled;
    dict->SetBoolean(key_names::kKeyUnlockKey, unlock_key);

    device_list->Append(std::move(dict));
  }

  // TODO(tengs): Rename this function after the easy_unlock app is replaced.
  SetRemoteDevices(*device_list);
}

proximity_auth::ProximityAuthPrefManager*
EasyUnlockServiceRegular::GetProximityAuthPrefManager() {
  return pref_manager_.get();
}

EasyUnlockService::Type EasyUnlockServiceRegular::GetType() const {
  return EasyUnlockService::TYPE_REGULAR;
}

AccountId EasyUnlockServiceRegular::GetAccountId() const {
  identity::IdentityManager* identity_manager =
      IdentityManagerFactory::GetForProfile(profile());
  // |profile| has to be a signed-in profile with IdentityManager already
  // created. Otherwise, just crash to collect stack.
  DCHECK(identity_manager);
  const AccountInfo account_info = identity_manager->GetPrimaryAccountInfo();
  // A regular signed-in (i.e., non-login) profile should always have an email.
  // TODO(crbug.com/857494): Enable this DCHECK once all browser tests create
  // correctly signed in profiles.
  // DCHECK(!account_info.email.empty());
  return account_info.email.empty()
             ? EmptyAccountId()
             : AccountId::FromUserEmailGaiaId(
                   gaia::CanonicalizeEmail(account_info.email),
                   account_info.gaia);
}

void EasyUnlockServiceRegular::SetHardlockAfterKeyOperation(
    EasyUnlockScreenlockStateHandler::HardlockState state_on_success,
    bool success) {
  if (success)
    SetHardlockStateForUser(GetAccountId(), state_on_success);

  // Even if the refresh keys operation suceeded, we still fetch and check the
  // cryptohome keys against the keys in local preferences as a sanity check.
  CheckCryptohomeKeysAndMaybeHardlock();
}

void EasyUnlockServiceRegular::ClearPermitAccess() {
  DictionaryPrefUpdate pairing_update(profile()->GetPrefs(),
                                      prefs::kEasyUnlockPairing);
  pairing_update->RemoveWithoutPathExpansion(kKeyPermitAccess, NULL);
}

const base::ListValue* EasyUnlockServiceRegular::GetRemoteDevices() const {
  const base::DictionaryValue* pairing_dict =
      profile()->GetPrefs()->GetDictionary(prefs::kEasyUnlockPairing);
  const base::ListValue* devices = NULL;
  if (pairing_dict && pairing_dict->GetList(kKeyDevices, &devices))
    return devices;
  return NULL;
}

void EasyUnlockServiceRegular::SetRemoteDevices(
    const base::ListValue& devices) {
  std::string remote_devices_json;
  JSONStringValueSerializer serializer(&remote_devices_json);
  serializer.Serialize(devices);
  PA_LOG(VERBOSE) << "Setting RemoteDevices:\n  " << remote_devices_json;

  DictionaryPrefUpdate pairing_update(profile()->GetPrefs(),
                                      prefs::kEasyUnlockPairing);
  if (devices.empty())
    pairing_update->RemoveWithoutPathExpansion(kKeyDevices, NULL);
  else
    pairing_update->SetKey(kKeyDevices, devices.Clone());

  RefreshCryptohomeKeysIfPossible();
}

std::string EasyUnlockServiceRegular::GetChallenge() const {
  return std::string();
}

std::string EasyUnlockServiceRegular::GetWrappedSecret() const {
  return std::string();
}

void EasyUnlockServiceRegular::RecordEasySignInOutcome(
    const AccountId& account_id,
    bool success) const {
  NOTREACHED();
}

void EasyUnlockServiceRegular::RecordPasswordLoginEvent(
    const AccountId& account_id) const {
  NOTREACHED();
}

void EasyUnlockServiceRegular::InitializeInternal() {
  proximity_auth::ScreenlockBridge::Get()->AddObserver(this);

  pref_manager_.reset(new proximity_auth::ProximityAuthProfilePrefManager(
      profile()->GetPrefs(), multidevice_setup_client_));

  // TODO(tengs): Due to badly configured browser_tests, Chrome crashes during
  // shutdown. Revisit this condition after migration is fully completed.
  if (!base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kTestType)) {
    // Note: There is no local state in tests.
    if (g_browser_process->local_state()) {
      pref_manager_->StartSyncingToLocalState(g_browser_process->local_state(),
                                              GetAccountId());
    }

    LoadRemoteDevices();
  }

  registrar_.Init(profile()->GetPrefs());
  registrar_.Add(
      proximity_auth::prefs::kProximityAuthIsChromeOSLoginEnabled,
      base::Bind(&EasyUnlockServiceRegular::RefreshCryptohomeKeysIfPossible,
                 weak_ptr_factory_.GetWeakPtr()));
}

void EasyUnlockServiceRegular::ShutdownInternal() {
  pref_manager_.reset();

  proximity_auth::ScreenlockBridge::Get()->RemoveObserver(this);

  registrar_.RemoveAll();

  device_sync_client_->RemoveObserver(this);

  multidevice_setup_client_->RemoveObserver(this);
}

bool EasyUnlockServiceRegular::IsAllowedInternal() const {
  user_manager::UserManager* user_manager = user_manager::UserManager::Get();
  if (!user_manager->IsLoggedInAsUserWithGaiaAccount())
    return false;

  // TODO(tengs): Ephemeral accounts generate a new enrollment every time they
  // are added, so disable Smart Lock to reduce enrollments on server. However,
  // ephemeral accounts can be locked, so we should revisit this use case.
  if (user_manager->IsCurrentUserNonCryptohomeDataEphemeral())
    return false;

  if (!ProfileHelper::IsPrimaryProfile(profile()))
    return false;

  if (feature_state_ ==
      multidevice_setup::mojom::FeatureState::kProhibitedByPolicy) {
    return false;
  }

  if (!profile()->GetPrefs()->GetBoolean(prefs::kEasyUnlockAllowed))
    return false;

  return true;
}

bool EasyUnlockServiceRegular::IsEnabled() const {
  // TODO(crbug.com/894585): Remove the legacy special case after M71.
  if (!IsInLegacyHostMode()) {
    return feature_state_ ==
           multidevice_setup::mojom::FeatureState::kEnabledByUser;
  }

  return pref_manager_ && pref_manager_->IsEasyUnlockEnabled();
}

bool EasyUnlockServiceRegular::IsChromeOSLoginEnabled() const {
  return pref_manager_ && pref_manager_->IsChromeOSLoginEnabled();
}

bool EasyUnlockServiceRegular::IsInLegacyHostMode() const {
  if (!device_sync_client_->is_ready()) {
    PA_LOG(WARNING) << "EasyUnlockServiceRegular::IsInLegacyHostMode: "
                    << "DeviceSyncClient not ready. Returning false.";
    return false;
  }

  bool has_supported_easy_unlock_host = false;
  for (const multidevice::RemoteDeviceRef& remote_device_ref :
       device_sync_client_->GetSyncedDevices()) {
    multidevice::SoftwareFeatureState better_together_host_state =
        remote_device_ref.GetSoftwareFeatureState(
            multidevice::SoftwareFeature::kBetterTogetherHost);
    // If there's any valid Better Together host, don't support legacy mode.
    if (better_together_host_state ==
            multidevice::SoftwareFeatureState::kSupported ||
        better_together_host_state ==
            multidevice::SoftwareFeatureState::kEnabled) {
      return false;
    }

    multidevice::SoftwareFeatureState easy_unlock_host_state =
        remote_device_ref.GetSoftwareFeatureState(
            multidevice::SoftwareFeature::kSmartLockHost);
    if (easy_unlock_host_state ==
            multidevice::SoftwareFeatureState::kSupported ||
        easy_unlock_host_state == multidevice::SoftwareFeatureState::kEnabled) {
      has_supported_easy_unlock_host = true;
    }
  }

  return has_supported_easy_unlock_host;
}

void EasyUnlockServiceRegular::OnSuspendDoneInternal() {
  lock_screen_last_shown_timestamp_ = base::TimeTicks::Now();
}

void EasyUnlockServiceRegular::OnReady() {
  // If the local device and synced devices are ready for the first time,
  // establish what the unlock keys were before the next sync. This is necessary
  // in order for OnNewDevicesSynced() to determine if new devices were added
  // since the last sync.
  remote_device_unlock_keys_before_sync_ = GetUnlockKeys();
}

void EasyUnlockServiceRegular::OnEnrollmentFinished() {
  // The local device may be ready for the first time, or it may have been
  // updated, so reload devices.
  LoadRemoteDevices();
}

void EasyUnlockServiceRegular::OnNewDevicesSynced() {
  std::set<std::string> public_keys_before_sync;
  for (const auto& remote_device : remote_device_unlock_keys_before_sync_) {
    public_keys_before_sync.insert(remote_device.public_key());
  }

  multidevice::RemoteDeviceRefList remote_device_unlock_keys_after_sync =
      GetUnlockKeys();
  std::set<std::string> public_keys_after_sync;
  for (const auto& remote_device : remote_device_unlock_keys_after_sync) {
    public_keys_after_sync.insert(remote_device.public_key());
  }

  ShowNotificationIfNewDevicePresent(public_keys_before_sync,
                                     public_keys_after_sync);

  LoadRemoteDevices();

  remote_device_unlock_keys_before_sync_ = remote_device_unlock_keys_after_sync;
}

void EasyUnlockServiceRegular::OnFeatureStatesChanged(
    const multidevice_setup::MultiDeviceSetupClient::FeatureStatesMap&
        feature_states_map) {
  // TODO(crbug.com/894585): Remove after M71.
  bool is_in_legacy_host_mode = IsInLegacyHostMode();
  if (pref_manager_)
    pref_manager_->SetIsInLegacyHostMode(is_in_legacy_host_mode);

  const auto it =
      feature_states_map.find(multidevice_setup::mojom::Feature::kSmartLock);
  if (it == feature_states_map.end()) {
    feature_state_ =
        multidevice_setup::mojom::FeatureState::kUnavailableNoVerifiedHost;
    if (!is_in_legacy_host_mode)
      return;
  } else {
    feature_state_ = it->second;
  }

  // Note: In order to properly start the EasyUnlock app when MultiDeviceSetup
  // is enabled, we must ensure that UpdateAppState() gets called when the
  // EasyUnlock feature-state changes from kProhibitedByPolicy to
  // kUnavailableNoVerifiedHost.
  if (is_in_legacy_host_mode)
    UpdateAppState();

  LoadRemoteDevices();
}

void EasyUnlockServiceRegular::ShowChromebookAddedNotification() {
  // The user may have decided to disable Smart Lock or the whole multidevice
  // suite immediately after completing setup, so ensure that Smart Lock is
  // enabled.
  if (feature_state_ == multidevice_setup::mojom::FeatureState::kEnabledByUser)
    notification_controller_->ShowChromebookAddedNotification();
}

void EasyUnlockServiceRegular::ShowNotificationIfNewDevicePresent(
    const std::set<std::string>& public_keys_before_sync,
    const std::set<std::string>& public_keys_after_sync) {
  if (public_keys_after_sync.empty())
    ClearPermitAccess();

  if (public_keys_before_sync == public_keys_after_sync)
    return;

  // Show the appropriate notification if an unlock key is first synced or if it
  // changes an existing key.
  // Note: We do not show a notification when EasyUnlock is disabled by sync nor
  // if EasyUnlock was enabled through the setup app.
  if (!public_keys_after_sync.empty()) {
    if (public_keys_before_sync.empty()) {
        multidevice_setup::MultiDeviceSetupDialog* multidevice_setup_dialog =
            multidevice_setup::MultiDeviceSetupDialog::Get();
        if (multidevice_setup_dialog) {
          // Delay showing the "Chromebook added" notification until the
          // MultiDeviceSetupDialog is closed.
          multidevice_setup_dialog->AddOnCloseCallback(base::BindOnce(
              &EasyUnlockServiceRegular::ShowChromebookAddedNotification,
              weak_ptr_factory_.GetWeakPtr()));
          return;
        }

      notification_controller_->ShowChromebookAddedNotification();
    } else {
      shown_pairing_changed_notification_ = true;
      notification_controller_->ShowPairingChangeNotification();
    }
  }
}

void EasyUnlockServiceRegular::OnForceSyncCompleted(bool success) {
  if (!success)
    PA_LOG(WARNING) << "Failed to force device sync.";
}

void EasyUnlockServiceRegular::OnScreenDidLock(
    proximity_auth::ScreenlockBridge::LockHandler::ScreenType screen_type) {
  set_will_authenticate_using_easy_unlock(false);
  lock_screen_last_shown_timestamp_ = base::TimeTicks::Now();
}

void EasyUnlockServiceRegular::OnScreenDidUnlock(
    proximity_auth::ScreenlockBridge::LockHandler::ScreenType screen_type) {
  // If we tried to load remote devices (e.g. after a sync or the
  // service was initialized) while the screen was locked, we can now
  // load the new remote devices.
  //
  // It's important to go through this code path even if unlocking the
  // login screen. Because when the service is initialized while the
  // user is signing in we need to load the remotes. Otherwise, the
  // first time the user locks the screen the feature won't work.
  if (deferring_device_load_) {
    PA_LOG(VERBOSE) << "Loading deferred devices after screen unlock.";
    deferring_device_load_ = false;
    LoadRemoteDevices();
  }

  // Do not process events for the login screen.
  if (screen_type != proximity_auth::ScreenlockBridge::LockHandler::LOCK_SCREEN)
    return;

  if (shown_pairing_changed_notification_) {
    shown_pairing_changed_notification_ = false;

    if (!GetUnlockKeys().empty()) {
      notification_controller_->ShowPairingChangeAppliedNotification(
          GetUnlockKeys()[0].name());
    }
  }

  // Only record metrics for users who have enabled the feature.
  if (IsEnabled()) {
    EasyUnlockAuthEvent event = will_authenticate_using_easy_unlock()
                                    ? EASY_UNLOCK_SUCCESS
                                    : GetPasswordAuthEvent();
    RecordEasyUnlockScreenUnlockEvent(event);

    if (will_authenticate_using_easy_unlock() ||
        event == PASSWORD_ENTRY_PHONE_LOCKED ||
        event == PASSWORD_ENTRY_PHONE_NOT_LOCKABLE ||
        event == PASSWORD_ENTRY_RSSI_TOO_LOW ||
        event == PASSWORD_ENTRY_PHONE_LOCKED_AND_RSSI_TOO_LOW ||
        event == PASSWORD_ENTRY_WITH_AUTHENTICATED_PHONE) {
      SmartLockMetricsRecorder::RecordGetRemoteStatusResultUnlockSuccess();
    }

    if (will_authenticate_using_easy_unlock()) {
      SmartLockMetricsRecorder::RecordSmartLockUnlockAuthMethodChoice(
          SmartLockMetricsRecorder::SmartLockAuthMethodChoice::kSmartLock);
      SmartLockMetricsRecorder::RecordAuthResultUnlockSuccess();
      RecordEasyUnlockScreenUnlockDuration(base::TimeTicks::Now() -
                                           lock_screen_last_shown_timestamp_);
    } else {
      SmartLockMetricsRecorder::RecordAuthMethodChoiceUnlockPasswordState(
          GetSmartUnlockPasswordAuthEvent());
      SmartLockMetricsRecorder::RecordSmartLockUnlockAuthMethodChoice(
          SmartLockMetricsRecorder::SmartLockAuthMethodChoice::kOther);
      OnUserEnteredPassword();
    }

    if (event == PASSWORD_ENTRY_BLUETOOTH_CONNECTING) {
      SmartLockMetricsRecorder::RecordGetRemoteStatusResultUnlockFailure(
          SmartLockMetricsRecorder::
              SmartLockGetRemoteStatusResultFailureReason::
                  kUserEnteredPasswordWhileConnecting);
    } else if (event == PASSWORD_ENTRY_NO_BLUETOOTH) {
      SmartLockMetricsRecorder::RecordGetRemoteStatusResultUnlockFailure(
          SmartLockMetricsRecorder::
              SmartLockGetRemoteStatusResultFailureReason::
                  kUserEnteredPasswordWhileBluetoothDisabled);
    }
  }

  set_will_authenticate_using_easy_unlock(false);
}

void EasyUnlockServiceRegular::OnFocusedUserChanged(
    const AccountId& account_id) {
  // Nothing to do.
}

void EasyUnlockServiceRegular::RefreshCryptohomeKeysIfPossible() {
  CheckCryptohomeKeysAndMaybeHardlock();
}

multidevice::RemoteDeviceRefList EasyUnlockServiceRegular::GetUnlockKeys() {
  multidevice::RemoteDeviceRefList unlock_keys;
  for (const auto& remote_device : device_sync_client_->GetSyncedDevices()) {
    bool unlock_key = remote_device.GetSoftwareFeatureState(
                          multidevice::SoftwareFeature::kSmartLockHost) ==
                      multidevice::SoftwareFeatureState::kEnabled;
    if (unlock_key)
      unlock_keys.push_back(remote_device);
  }
  return unlock_keys;
}

}  // namespace chromeos
