// Copyright 2019 The Chromium OS 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 "kerberos/kerberos_metrics.h"

#include <utility>

#include <base/files/file_util.h>
#include <base/strings/stringprintf.h>
#include <base/time/clock.h>
#include "base/time/default_clock.h"

namespace kerberos {

namespace {

// Prefix for all UMA stats.
constexpr char kKerberos[] = "Kerberos.";

// Prefix for Kerberos.Result.<method name> stats.
constexpr char kResult[] = "Result.";

// Stat for the result of a ValidateConfig call.
constexpr char kValidateConfigErrorCode[] = "ValidateConfigErrorCode";

// Stat for the encryption types used on Kerberos TGT creation.
constexpr char kEncryptionTypesAcquireKerberosTgt[] =
    "EncryptionTypesAcquireKerberosTgt";

// Stat for counting user types, see |UserType|.
constexpr char kDailyActiveUsers[] = "DailyActiveUsers";

// Prefix for UMA stats that are counting accounts.
constexpr char kNumberOfAccounts[] = "NumberOfAccounts.";

// Stat names for counting accounts, prefixed by "Kerberos.NumberOfAccounts.".
constexpr char kTotal[] = "Total";
constexpr char kManaged[] = "Managed";
constexpr char kUnmanaged[] = "Unmanaged";
constexpr char kRememberedPassword[] = "RememberedPassword";
constexpr char kUseLoginPassword[] = "UseLoginPassword";

// Max number of accounts for UMA stats.
constexpr int kMaxAccounts = 10;

// Used to rate limit some UMA stats to once a day.
constexpr char kDailyReportTimeFile[] = "daily_report_timestamp";

// User type to be sent to Kerberos.DailyActiveUsers. These values (except
// UserType::kCount, which should be last) are persisted to logs. Entries should
// not be renumbered and numeric values should never be reused.
enum class UserType { kManaged = 0, kUnmanaged = 1, kCount = 2 };

}  // namespace

KerberosMetrics::KerberosMetrics(const base::FilePath& storage_dir)
    : kerberos_(kKerberos),
      acquire_tgt_timer_(kerberos_ + "AcquireKerberosTgtTime",
                         1 /* min 1 millisecond */,
                         20000 /* max 20 seconds */,
                         50 /* bucket count */),
      daily_report_time_path_(storage_dir.Append(kDailyReportTimeFile)),
      clock_(std::make_unique<base::DefaultClock>()) {
  chromeos_metrics::TimerReporter::set_metrics_lib(&metrics_lib_);
}

KerberosMetrics::~KerberosMetrics() {
  chromeos_metrics::TimerReporter::set_metrics_lib(nullptr);
}

void KerberosMetrics::StartAcquireTgtTimer() {
  DCHECK(!acquire_tgt_timer_.HasStarted());
  acquire_tgt_timer_.Start();
}

void KerberosMetrics::StopAcquireTgtTimerAndReport() {
  DCHECK(acquire_tgt_timer_.HasStarted());
  acquire_tgt_timer_.Stop();
  acquire_tgt_timer_.ReportMilliseconds();
}

void KerberosMetrics::ReportDBusCallResult(const std::string& method_name,
                                           ErrorType error) {
  metrics_lib_.SendEnumToUMA(kerberos_ + kResult + method_name,
                             static_cast<int>(error),
                             static_cast<int>(ERROR_COUNT));
}

void KerberosMetrics::ReportValidateConfigErrorCode(ConfigErrorCode code) {
  metrics_lib_.SendEnumToUMA(kerberos_ + kValidateConfigErrorCode,
                             static_cast<int>(code),
                             static_cast<int>(CONFIG_ERROR_COUNT));
}

void KerberosMetrics::ReportKerberosEncryptionTypes(
    KerberosEncryptionTypes types) {
  metrics_lib_.SendEnumToUMA(kerberos_ + kEncryptionTypesAcquireKerberosTgt,
                             static_cast<int>(types),
                             static_cast<int>(KerberosEncryptionTypes::kCount));
}

bool KerberosMetrics::ShouldReportDailyUsageStats() {
  const base::Time now = clock_->Now();

  base::File::Info info;
  if (!base::GetFileInfo(daily_report_time_path_, &info)) {
    // Create the file. Don't skew stats if something goes wrong. Note that
    // base::TouchFile bails if the file doesn't exist!
    const bool res =
        base::WriteFile(daily_report_time_path_, nullptr, 0) == 0 &&
        base::TouchFile(daily_report_time_path_, now, now);
    if (!res)
      LOG(WARNING) << "Failed to touch " << daily_report_time_path_.value();
    return res;
  }

  // Be sure to gracefully handle the case when the clock is moved backwards.
  const base::Time last_file_time = info.last_modified;
  int days_elapsed = (now - last_file_time).InDays();
  if (days_elapsed == 0)
    return false;

  // Don't set the new file time to |now|. This would result in an average
  // frequency of less than one day.
  base::Time new_time =
      last_file_time + days_elapsed * base::TimeDelta::FromDays(1);
  const bool res = base::TouchFile(daily_report_time_path_, new_time, new_time);
  if (!res)
    LOG(WARNING) << "Failed to touch " << daily_report_time_path_.value();

  // Don't report if time goes backwards (but do reset the file time!).
  return days_elapsed > 0;
}

void KerberosMetrics::ReportDailyUsageStats(int total_count,
                                            int managed_count,
                                            int unmanaged_count,
                                            int remembered_password_count,
                                            int use_login_password_count) {
  // TODO(https://crbug.com/984552): Send the proper user type once unmanaged
  // users can use this feature.
  metrics_lib_.SendEnumToUMA(kerberos_ + kDailyActiveUsers,
                             static_cast<int>(UserType::kManaged),
                             static_cast<int>(UserType::kCount));

  SendAccountCount(kTotal, total_count);
  SendAccountCount(kManaged, managed_count);
  SendAccountCount(kUnmanaged, unmanaged_count);
  SendAccountCount(kRememberedPassword, remembered_password_count);
  SendAccountCount(kUseLoginPassword, use_login_password_count);
}

void KerberosMetrics::SetClockForTesting(std::unique_ptr<base::Clock> clock) {
  clock_ = std::move(clock);
}

void KerberosMetrics::SendAccountCount(const char* name, int count) {
  metrics_lib_.SendToUMA(kerberos_ + kNumberOfAccounts + name, count, 1,
                         kMaxAccounts, kMaxAccounts + 1);
}

}  // namespace kerberos
