// 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 "components/cryptauth/cryptauth_enrollment_manager_impl.h"

#include <memory>
#include <sstream>
#include <utility>

#include "base/base64url.h"
#include "base/memory/ptr_util.h"
#include "base/time/clock.h"
#include "base/time/time.h"
#include "chromeos/components/proximity_auth/logging/logging.h"
#include "components/cryptauth/cryptauth_enroller.h"
#include "components/cryptauth/pref_names.h"
#include "components/cryptauth/proto/enum_util.h"
#include "components/cryptauth/secure_message_delegate.h"
#include "components/cryptauth/sync_scheduler_impl.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"

namespace cryptauth {

namespace {

// The number of days that an enrollment is valid. Note that we try to refresh
// the enrollment well before this time elapses.
const int kValidEnrollmentPeriodDays = 45;

// The normal period between successful enrollments in days.
const int kEnrollmentRefreshPeriodDays = 30;

// A more aggressive period between enrollments to recover when the last
// enrollment fails, in minutes. This is a base time that increases for each
// subsequent failure.
const int kEnrollmentBaseRecoveryPeriodMinutes = 10;

// The bound on the amount to jitter the period between enrollments.
const double kEnrollmentMaxJitterRatio = 0.2;

// The value of the device_software_package field in the device info uploaded
// during enrollment. This value must be the same as the app id used for GCM
// registration.
const char kDeviceSoftwarePackage[] = "com.google.chrome.cryptauth";

std::unique_ptr<SyncScheduler> CreateSyncScheduler(
    SyncScheduler::Delegate* delegate) {
  return std::make_unique<SyncSchedulerImpl>(
      delegate, base::TimeDelta::FromDays(kEnrollmentRefreshPeriodDays),
      base::TimeDelta::FromMinutes(kEnrollmentBaseRecoveryPeriodMinutes),
      kEnrollmentMaxJitterRatio, "CryptAuth Enrollment");
}

std::string GenerateSupportedFeaturesString(const GcmDeviceInfo& info) {
  std::stringstream ss;
  ss << "[";

  bool logged_feature = false;
  for (int i = 0; i < info.supported_software_features_size(); ++i) {
    logged_feature = true;
    ss << info.supported_software_features(i) << ", ";
  }

  if (logged_feature)
    ss.seekp(-2, ss.cur);  // Remove last ", " from the stream.

  ss << "]";
  return ss.str();
}

}  // namespace

// static
CryptAuthEnrollmentManagerImpl::Factory*
    CryptAuthEnrollmentManagerImpl::Factory::factory_instance_ = nullptr;

// static
std::unique_ptr<CryptAuthEnrollmentManager>
CryptAuthEnrollmentManagerImpl::Factory::NewInstance(
    base::Clock* clock,
    std::unique_ptr<CryptAuthEnrollerFactory> enroller_factory,
    std::unique_ptr<SecureMessageDelegate> secure_message_delegate,
    const GcmDeviceInfo& device_info,
    CryptAuthGCMManager* gcm_manager,
    PrefService* pref_service) {
  if (!factory_instance_)
    factory_instance_ = new Factory();

  return factory_instance_->BuildInstance(
      clock, std::move(enroller_factory), std::move(secure_message_delegate),
      device_info, gcm_manager, pref_service);
}

// static
void CryptAuthEnrollmentManagerImpl::Factory::SetInstanceForTesting(
    Factory* factory) {
  factory_instance_ = factory;
}

CryptAuthEnrollmentManagerImpl::Factory::~Factory() = default;

std::unique_ptr<CryptAuthEnrollmentManager>
CryptAuthEnrollmentManagerImpl::Factory::BuildInstance(
    base::Clock* clock,
    std::unique_ptr<CryptAuthEnrollerFactory> enroller_factory,
    std::unique_ptr<SecureMessageDelegate> secure_message_delegate,
    const GcmDeviceInfo& device_info,
    CryptAuthGCMManager* gcm_manager,
    PrefService* pref_service) {
  return base::WrapUnique(new CryptAuthEnrollmentManagerImpl(
      clock, std::move(enroller_factory), std::move(secure_message_delegate),
      device_info, gcm_manager, pref_service));
}

CryptAuthEnrollmentManagerImpl::CryptAuthEnrollmentManagerImpl(
    base::Clock* clock,
    std::unique_ptr<CryptAuthEnrollerFactory> enroller_factory,
    std::unique_ptr<SecureMessageDelegate> secure_message_delegate,
    const GcmDeviceInfo& device_info,
    CryptAuthGCMManager* gcm_manager,
    PrefService* pref_service)
    : clock_(clock),
      enroller_factory_(std::move(enroller_factory)),
      secure_message_delegate_(std::move(secure_message_delegate)),
      device_info_(device_info),
      gcm_manager_(gcm_manager),
      pref_service_(pref_service),
      scheduler_(CreateSyncScheduler(this /* delegate */)),
      weak_ptr_factory_(this) {}

CryptAuthEnrollmentManagerImpl::~CryptAuthEnrollmentManagerImpl() {
  gcm_manager_->RemoveObserver(this);
}

void CryptAuthEnrollmentManagerImpl::Start() {
  gcm_manager_->AddObserver(this);

  bool is_recovering_from_failure =
      pref_service_->GetBoolean(
          prefs::kCryptAuthEnrollmentIsRecoveringFromFailure) ||
      !IsEnrollmentValid();

  base::Time last_successful_enrollment = GetLastEnrollmentTime();
  base::TimeDelta elapsed_time_since_last_sync =
      clock_->Now() - last_successful_enrollment;

  scheduler_->Start(elapsed_time_since_last_sync,
                    is_recovering_from_failure
                        ? SyncScheduler::Strategy::AGGRESSIVE_RECOVERY
                        : SyncScheduler::Strategy::PERIODIC_REFRESH);
}

void CryptAuthEnrollmentManagerImpl::ForceEnrollmentNow(
    InvocationReason invocation_reason) {
  // We store the invocation reason in a preference so that it can persist
  // across browser restarts. If the sync fails, the next retry should still use
  // this original reason instead of INVOCATION_REASON_FAILURE_RECOVERY.
  pref_service_->SetInteger(prefs::kCryptAuthEnrollmentReason,
                            invocation_reason);
  scheduler_->ForceSync();
}

bool CryptAuthEnrollmentManagerImpl::IsEnrollmentValid() const {
  base::Time last_enrollment_time = GetLastEnrollmentTime();
  return !last_enrollment_time.is_null() &&
         (clock_->Now() - last_enrollment_time) <
             base::TimeDelta::FromDays(kValidEnrollmentPeriodDays);
}

base::Time CryptAuthEnrollmentManagerImpl::GetLastEnrollmentTime() const {
  return base::Time::FromDoubleT(pref_service_->GetDouble(
      prefs::kCryptAuthEnrollmentLastEnrollmentTimeSeconds));
}

base::TimeDelta CryptAuthEnrollmentManagerImpl::GetTimeToNextAttempt() const {
  return scheduler_->GetTimeToNextSync();
}

bool CryptAuthEnrollmentManagerImpl::IsEnrollmentInProgress() const {
  return scheduler_->GetSyncState() ==
         SyncScheduler::SyncState::SYNC_IN_PROGRESS;
}

bool CryptAuthEnrollmentManagerImpl::IsRecoveringFromFailure() const {
  return scheduler_->GetStrategy() ==
         SyncScheduler::Strategy::AGGRESSIVE_RECOVERY;
}

void CryptAuthEnrollmentManagerImpl::OnEnrollmentFinished(bool success) {
  if (success) {
    pref_service_->SetDouble(
        prefs::kCryptAuthEnrollmentLastEnrollmentTimeSeconds,
        clock_->Now().ToDoubleT());
    pref_service_->SetInteger(prefs::kCryptAuthEnrollmentReason,
                              INVOCATION_REASON_UNKNOWN);
  }

  pref_service_->SetBoolean(prefs::kCryptAuthEnrollmentIsRecoveringFromFailure,
                            !success);

  sync_request_->OnDidComplete(success);
  cryptauth_enroller_.reset();
  sync_request_.reset();

  NotifyEnrollmentFinished(success);
}

std::string CryptAuthEnrollmentManagerImpl::GetUserPublicKey() const {
  std::string public_key;
  if (!base::Base64UrlDecode(
          pref_service_->GetString(prefs::kCryptAuthEnrollmentUserPublicKey),
          base::Base64UrlDecodePolicy::REQUIRE_PADDING, &public_key)) {
    PA_LOG(ERROR) << "Invalid public key stored in user prefs.";
    return std::string();
  }
  return public_key;
}

std::string CryptAuthEnrollmentManagerImpl::GetUserPrivateKey() const {
  std::string private_key;
  if (!base::Base64UrlDecode(
          pref_service_->GetString(prefs::kCryptAuthEnrollmentUserPrivateKey),
          base::Base64UrlDecodePolicy::REQUIRE_PADDING, &private_key)) {
    PA_LOG(ERROR) << "Invalid private key stored in user prefs.";
    return std::string();
  }
  return private_key;
}

void CryptAuthEnrollmentManagerImpl::SetSyncSchedulerForTest(
    std::unique_ptr<SyncScheduler> sync_scheduler) {
  scheduler_ = std::move(sync_scheduler);
}

void CryptAuthEnrollmentManagerImpl::OnGCMRegistrationResult(bool success) {
  if (!sync_request_)
    return;

  PA_LOG(INFO) << "GCM registration for CryptAuth Enrollment completed: "
               << success;
  if (success)
    DoCryptAuthEnrollment();
  else
    OnEnrollmentFinished(false);
}

void CryptAuthEnrollmentManagerImpl::OnKeyPairGenerated(
    const std::string& public_key,
    const std::string& private_key) {
  if (!public_key.empty() && !private_key.empty()) {
    PA_LOG(INFO) << "Key pair generated for CryptAuth enrollment";
    // Store the keypair in Base64 format because pref values require readable
    // string values.
    std::string public_key_b64, private_key_b64;
    base::Base64UrlEncode(public_key,
                          base::Base64UrlEncodePolicy::INCLUDE_PADDING,
                          &public_key_b64);
    base::Base64UrlEncode(private_key,
                          base::Base64UrlEncodePolicy::INCLUDE_PADDING,
                          &private_key_b64);
    pref_service_->SetString(prefs::kCryptAuthEnrollmentUserPublicKey,
                             public_key_b64);
    pref_service_->SetString(prefs::kCryptAuthEnrollmentUserPrivateKey,
                             private_key_b64);
    DoCryptAuthEnrollment();
  } else {
    OnEnrollmentFinished(false);
  }
}

void CryptAuthEnrollmentManagerImpl::OnReenrollMessage() {
  ForceEnrollmentNow(INVOCATION_REASON_SERVER_INITIATED);
}

void CryptAuthEnrollmentManagerImpl::OnSyncRequested(
    std::unique_ptr<SyncScheduler::SyncRequest> sync_request) {
  NotifyEnrollmentStarted();

  sync_request_ = std::move(sync_request);
  if (gcm_manager_->GetRegistrationId().empty() ||
      pref_service_->GetInteger(prefs::kCryptAuthEnrollmentReason) ==
          INVOCATION_REASON_MANUAL) {
    gcm_manager_->RegisterWithGCM();
  } else {
    DoCryptAuthEnrollment();
  }
}

void CryptAuthEnrollmentManagerImpl::DoCryptAuthEnrollment() {
  if (GetUserPublicKey().empty() || GetUserPrivateKey().empty()) {
    secure_message_delegate_->GenerateKeyPair(
        base::Bind(&CryptAuthEnrollmentManagerImpl::OnKeyPairGenerated,
                   weak_ptr_factory_.GetWeakPtr()));
  } else {
    DoCryptAuthEnrollmentWithKeys();
  }
}

void CryptAuthEnrollmentManagerImpl::DoCryptAuthEnrollmentWithKeys() {
  DCHECK(sync_request_);
  InvocationReason invocation_reason = INVOCATION_REASON_UNKNOWN;

  int reason_stored_in_prefs =
      pref_service_->GetInteger(prefs::kCryptAuthEnrollmentReason);

  if (InvocationReason_IsValid(reason_stored_in_prefs) &&
      reason_stored_in_prefs != INVOCATION_REASON_UNKNOWN) {
    invocation_reason = static_cast<InvocationReason>(reason_stored_in_prefs);
  } else if (GetLastEnrollmentTime().is_null()) {
    invocation_reason = INVOCATION_REASON_INITIALIZATION;
  } else if (!IsEnrollmentValid()) {
    invocation_reason = INVOCATION_REASON_EXPIRATION;
  } else if (scheduler_->GetStrategy() ==
             SyncScheduler::Strategy::PERIODIC_REFRESH) {
    invocation_reason = INVOCATION_REASON_PERIODIC;
  } else if (scheduler_->GetStrategy() ==
             SyncScheduler::Strategy::AGGRESSIVE_RECOVERY) {
    invocation_reason = INVOCATION_REASON_FAILURE_RECOVERY;
  }

  // Fill in the current GCM registration id before enrolling, and explicitly
  // make sure that the software package is the same as the GCM app id.
  GcmDeviceInfo device_info(device_info_);
  device_info.set_gcm_registration_id(gcm_manager_->GetRegistrationId());
  device_info.set_device_software_package(kDeviceSoftwarePackage);

  std::string public_key_b64;
  base::Base64UrlEncode(GetUserPublicKey(),
                        base::Base64UrlEncodePolicy::INCLUDE_PADDING,
                        &public_key_b64);
  PA_LOG(INFO) << "Making enrollment:\n"
               << "  public_key: " << public_key_b64 << "\n"
               << "  invocation_reason: " << invocation_reason << "\n"
               << "  gcm_registration_id: " << device_info.gcm_registration_id()
               << "  supported features: "
               << GenerateSupportedFeaturesString(device_info);

  cryptauth_enroller_ = enroller_factory_->CreateInstance();
  cryptauth_enroller_->Enroll(
      GetUserPublicKey(), GetUserPrivateKey(), device_info, invocation_reason,
      base::Bind(&CryptAuthEnrollmentManagerImpl::OnEnrollmentFinished,
                 weak_ptr_factory_.GetWeakPtr()));
}

}  // namespace cryptauth
