// Copyright (c) 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 "components/browser_watcher/watcher_metrics_provider_win.h"

#include <stddef.h>

#include <limits>
#include <memory>
#include <set>
#include <utility>
#include <vector>

#include "base/bind.h"
#include "base/feature_list.h"
#include "base/metrics/field_trial_params.h"
#include "base/metrics/histogram.h"
#include "base/metrics/histogram_base.h"
#include "base/metrics/histogram_macros.h"
#include "base/metrics/sparse_histogram.h"
#include "base/process/process.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task_scheduler/post_task.h"
#include "base/task_scheduler/task_traits.h"
#include "base/win/registry.h"
#include "components/browser_watcher/features.h"
#include "components/browser_watcher/postmortem_report_collector.h"
#include "components/browser_watcher/stability_paths.h"
#include "components/browser_watcher/system_session_analyzer_win.h"
#include "third_party/crashpad/crashpad/client/crash_report_database.h"

namespace browser_watcher {

namespace {

// Process ID APIs on Windows talk in DWORDs, whereas for string formatting
// and parsing, this code uses int. In practice there are no process IDs with
// the high bit set on Windows, so there's no danger of overflow if this is
// done consistently.
static_assert(sizeof(DWORD) == sizeof(int),
              "process ids are expected to be no larger than int");

// This function does soft matching on the PID recorded in the key only.
// Due to PID reuse, the possibility exists that the process that's now live
// with the given PID is not the same process the data was recorded for.
// This doesn't matter for the purpose, as eventually the data will be
// scavenged and reported.
bool IsDeadProcess(base::StringPiece16 key_or_value_name) {
  // Truncate the input string to the first occurrence of '-', if one exists.
  size_t num_end = key_or_value_name.find(L'-');
  if (num_end != base::StringPiece16::npos)
    key_or_value_name = key_or_value_name.substr(0, num_end);

  // Convert to the numeric PID.
  int pid = 0;
  if (!base::StringToInt(key_or_value_name, &pid) || pid == 0)
    return true;

  // This is a very inexpensive check for the common case of our own PID.
  if (static_cast<base::ProcessId>(pid) == base::GetCurrentProcId())
    return false;

  // The process is not our own - see whether a process with this PID exists.
  // This is more expensive than the above check, but should also be very rare,
  // as this only happens more than once for a given PID if a user is running
  // multiple Chrome instances concurrently.
  base::Process process =
      base::Process::Open(static_cast<base::ProcessId>(pid));
  if (process.IsValid()) {
    // The fact that it was possible to open the process says it's live.
    return false;
  }

  return true;
}

void RecordExitCodes(const base::string16& registry_path) {
  base::win::RegKey regkey(HKEY_CURRENT_USER,
                           registry_path.c_str(),
                           KEY_QUERY_VALUE | KEY_SET_VALUE);
  if (!regkey.Valid())
    return;

  size_t num = regkey.GetValueCount();
  if (num == 0)
    return;
  std::vector<base::string16> to_delete;

  // Record the exit codes in a sparse stability histogram, as the range of
  // values used to report failures is large.
  base::HistogramBase* exit_code_histogram =
      base::SparseHistogram::FactoryGet(
          WatcherMetricsProviderWin::kBrowserExitCodeHistogramName,
          base::HistogramBase::kUmaStabilityHistogramFlag);

  for (size_t i = 0; i < num; ++i) {
    base::string16 name;
    if (regkey.GetValueNameAt(static_cast<int>(i), &name) == ERROR_SUCCESS) {
      DWORD exit_code = 0;
      if (regkey.ReadValueDW(name.c_str(), &exit_code) == ERROR_SUCCESS) {
        // Do not report exit codes for processes that are still live,
        // notably for our own process.
        if (exit_code != STILL_ACTIVE || IsDeadProcess(name)) {
          to_delete.push_back(name);
          exit_code_histogram->Add(exit_code);
        }
      }
    }
  }

  // Delete the values reported above.
  for (size_t i = 0; i < to_delete.size(); ++i)
    regkey.DeleteValue(to_delete[i].c_str());
}

void DeleteAllValues(base::win::RegKey* key) {
  DCHECK(key);

  while (key->GetValueCount() != 0) {
    base::string16 value_name;
    LONG res = key->GetValueNameAt(0, &value_name);
    if (res != ERROR_SUCCESS) {
      DVLOG(1) << "Failed to get value name " << res;
      return;
    }

    res = key->DeleteValue(value_name.c_str());
    if (res != ERROR_SUCCESS) {
      DVLOG(1) << "Failed to delete value " << value_name;
      return;
    }
  }
}

// Called from the blocking pool when metrics reporting is disabled, as there
// may be a sizable stash of data to delete.
void DeleteExitCodeRegistryKey(const base::string16& registry_path) {
  CHECK_NE(L"", registry_path);

  base::win::RegKey key;
  LONG res = key.Open(HKEY_CURRENT_USER, registry_path.c_str(),
                      KEY_QUERY_VALUE | KEY_SET_VALUE);
  if (res == ERROR_SUCCESS) {
    DeleteAllValues(&key);
    res = key.DeleteEmptyKey(L"");
  }
  if (res != ERROR_FILE_NOT_FOUND && res != ERROR_SUCCESS)
    DVLOG(1) << "Failed to delete exit code key " << registry_path;
}

enum CollectionInitializationStatus {
  INIT_SUCCESS = 0,
  UNKNOWN_DIR = 1,
  GET_STABILITY_FILE_PATH_FAILED = 2,
  CRASHPAD_DATABASE_INIT_FAILED = 3,
  INIT_STATUS_MAX = 4
};

void LogCollectionInitStatus(CollectionInitializationStatus status) {
  UMA_HISTOGRAM_ENUMERATION("ActivityTracker.Collect.InitStatus", status,
                            INIT_STATUS_MAX);
}

// Returns a task runner appropriate for running background tasks that perform
// file I/O.
scoped_refptr<base::TaskRunner> CreateBackgroundTaskRunner() {
  return base::CreateSequencedTaskRunnerWithTraits(
      {base::MayBlock(), base::TaskPriority::BACKGROUND,
       base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN});
}

}  // namespace

const char WatcherMetricsProviderWin::kBrowserExitCodeHistogramName[] =
    "Stability.BrowserExitCodes";

WatcherMetricsProviderWin::WatcherMetricsProviderWin(
    const base::string16& registry_path,
    const base::FilePath& user_data_dir,
    const base::FilePath& crash_dir,
    const GetExecutableDetailsCallback& exe_details_cb)
    : recording_enabled_(false),
      cleanup_scheduled_(false),
      registry_path_(registry_path),
      user_data_dir_(user_data_dir),
      crash_dir_(crash_dir),
      exe_details_cb_(exe_details_cb),
      task_runner_(CreateBackgroundTaskRunner()),
      weak_ptr_factory_(this) {}

WatcherMetricsProviderWin::~WatcherMetricsProviderWin() {
}

void WatcherMetricsProviderWin::OnRecordingEnabled() {
  recording_enabled_ = true;
}

void WatcherMetricsProviderWin::OnRecordingDisabled() {
  if (!recording_enabled_ && !cleanup_scheduled_) {
    // When metrics reporting is disabled, the providers get an
    // OnRecordingDisabled notification at startup. Use that first notification
    // to issue the cleanup task. Runs in the background because interacting
    // with the registry can block.
    task_runner_->PostTask(
        FROM_HERE, base::BindOnce(&DeleteExitCodeRegistryKey, registry_path_));

    cleanup_scheduled_ = true;
  }
}

void WatcherMetricsProviderWin::ProvideStabilityMetrics(
    metrics::SystemProfileProto* /* system_profile_proto */) {
  // Note that if there are multiple instances of Chrome running in the same
  // user account, there's a small race that will double-report the exit codes
  // from both/multiple instances. This ought to be vanishingly rare and will
  // only manifest as low-level "random" noise. To work around this it would be
  // necessary to implement some form of global locking, which is not worth it
  // here.
  RecordExitCodes(registry_path_);
}

void WatcherMetricsProviderWin::AsyncInit(const base::Closure& done_callback) {
  task_runner_->PostTaskAndReply(
      FROM_HERE,
      base::BindOnce(&WatcherMetricsProviderWin::CollectPostmortemReportsImpl,
                     weak_ptr_factory_.GetWeakPtr()),
      done_callback);
}

// TODO(manzagop): consider mechanisms for partial collection if this is to be
//     used on a critical path.
void WatcherMetricsProviderWin::CollectPostmortemReportsImpl() {
  SCOPED_UMA_HISTOGRAM_TIMER("ActivityTracker.Collect.TotalTime");

  bool is_stability_debugging_on =
      base::FeatureList::IsEnabled(browser_watcher::kStabilityDebuggingFeature);
  if (!is_stability_debugging_on) {
    return;  // TODO(manzagop): scan for possible data to delete?
  }

  if (user_data_dir_.empty() || crash_dir_.empty()) {
    LogCollectionInitStatus(UNKNOWN_DIR);
    return;
  }

  // Determine which files to harvest.
  base::FilePath stability_dir = GetStabilityDir(user_data_dir_);

  base::FilePath current_stability_file;
  if (!GetStabilityFileForProcess(base::Process::Current(), user_data_dir_,
                                  &current_stability_file)) {
    LogCollectionInitStatus(GET_STABILITY_FILE_PATH_FAILED);
    return;
  }
  const std::set<base::FilePath>& excluded_stability_files = {
      current_stability_file};

  std::vector<base::FilePath> stability_files = GetStabilityFiles(
      stability_dir, GetStabilityFilePattern(), excluded_stability_files);
  UMA_HISTOGRAM_COUNTS_100("ActivityTracker.Collect.StabilityFileCount",
                           stability_files.size());

  // If postmortem collection is disabled, delete the files.
  const bool should_collect = base::GetFieldTrialParamByFeatureAsBool(
      browser_watcher::kStabilityDebuggingFeature,
      browser_watcher::kCollectPostmortemParam, false);

  // Create a database. Note: Chrome already has a g_database in crashpad.cc but
  // it has internal linkage. Create a new one.
  std::unique_ptr<crashpad::CrashReportDatabase> crashpad_database;
  if (should_collect) {
    crashpad_database =
        crashpad::CrashReportDatabase::InitializeWithoutCreating(crash_dir_);
    if (!crashpad_database) {
      LOG(ERROR) << "Failed to initialize a CrashPad database.";
      LogCollectionInitStatus(CRASHPAD_DATABASE_INIT_FAILED);
      // Note: continue to processing the files anyway.
    }
  }

  // Note: this is logged even when Crashpad database initialization fails.
  LogCollectionInitStatus(INIT_SUCCESS);

  const size_t kSystemSessionsToInspect = 5U;
  SystemSessionAnalyzer analyzer(kSystemSessionsToInspect);

  if (should_collect) {
    base::string16 product_name, version_number, channel_name;
    exe_details_cb_.Run(&product_name, &version_number, &channel_name);
    PostmortemReportCollector collector(
        base::UTF16ToUTF8(product_name), base::UTF16ToUTF8(version_number),
        base::UTF16ToUTF8(channel_name), crashpad_database.get(), &analyzer);
    collector.Process(stability_files);
  } else {
    PostmortemReportCollector collector(&analyzer);
    collector.Process(stability_files);
  }
}

}  // namespace browser_watcher
