chromium/components/metrics/clean_exit_beacon.cc

// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "components/metrics/clean_exit_beacon.h"

#include <algorithm>
#include <memory>
#include <utility>

#include "base/check_op.h"
#include "base/command_line.h"
#include "base/files/file_util.h"
#include "base/json/json_file_value_serializer.h"
#include "base/json/json_string_value_serializer.h"
#include "base/logging.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/path_service.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/threading/thread_restrictions.h"
#include "build/build_config.h"
#include "components/metrics/metrics_pref_names.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
#include "components/variations/pref_names.h"
#include "components/variations/variations_switches.h"

#if BUILDFLAG(IS_WIN)
#include <windows.h>

#include "base/strings/string_util_win.h"
#include "base/strings/utf_string_conversions.h"
#include "base/win/registry.h"
#endif

namespace metrics {

namespace {

kVariationsCrashStreak;

// Denotes whether Chrome should perform clean shutdown steps: signaling that
// Chrome is exiting cleanly and then CHECKing that is has shutdown cleanly.
// This may be modified by SkipCleanShutdownStepsForTesting().
bool g_skip_clean_shutdown_steps =;

#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_IOS)
// Records the the combined state of two distinct beacons' values in a
// histogram.
void RecordBeaconConsistency(
    std::optional<bool> beacon_file_beacon_value,
    std::optional<bool> platform_specific_beacon_value) {
  CleanExitBeaconConsistency consistency =
      CleanExitBeaconConsistency::kDirtyDirty;

  if (!beacon_file_beacon_value) {
    if (!platform_specific_beacon_value) {
      consistency = CleanExitBeaconConsistency::kMissingMissing;
    } else {
      consistency = platform_specific_beacon_value.value()
                        ? CleanExitBeaconConsistency::kMissingClean
                        : CleanExitBeaconConsistency::kMissingDirty;
    }
  } else if (!platform_specific_beacon_value) {
    consistency = beacon_file_beacon_value.value()
                      ? CleanExitBeaconConsistency::kCleanMissing
                      : CleanExitBeaconConsistency::kDirtyMissing;
  } else if (beacon_file_beacon_value.value()) {
    consistency = platform_specific_beacon_value.value()
                      ? CleanExitBeaconConsistency::kCleanClean
                      : CleanExitBeaconConsistency::kCleanDirty;
  } else {
    consistency = platform_specific_beacon_value.value()
                      ? CleanExitBeaconConsistency::kDirtyClean
                      : CleanExitBeaconConsistency::kDirtyDirty;
  }
  base::UmaHistogramEnumeration("UMA.CleanExitBeaconConsistency3", consistency);
}
#endif  // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_IOS)

// Increments kVariationsCrashStreak if |did_previous_session_exit_cleanly| is
// false. Also, emits the crash streak to a histogram.
//
// If |beacon_file_contents| are given, then the beacon file is used to retrieve
// the crash streak. Otherwise, |local_state| is used.
void MaybeIncrementCrashStreak(bool did_previous_session_exit_cleanly,
                               base::Value* beacon_file_contents,
                               PrefService* local_state) {}

// Records |file_state| in a histogram.
void RecordBeaconFileState(BeaconFileState file_state) {}

// Returns the contents of the file at |beacon_file_path| if the following
// conditions are all true. Otherwise, returns nullptr.
//
// 1. The file path is non-empty.
// 2. The file exists.
// 3. The file is successfully read.
// 4. The file contents are in the expected format with the expected info.
//
// The file may not exist for the below reasons:
//
// 1. The file is unsupported on the platform.
// 2. This is the first session after a client updates to or installs a Chrome
//    version that uses the beacon file. The beacon file launched on desktop
//    and iOS in M102 and on Android Chrome in M103.
// 3. Android Chrome clients with only background sessions may never write a
//    beacon file.
// 4. A user may delete the file.
std::unique_ptr<base::Value> MaybeGetFileContents(
    const base::FilePath& beacon_file_path) {}

}  // namespace

const base::FilePath::CharType kCleanExitBeaconFilename[] =);

CleanExitBeacon::CleanExitBeacon(const std::wstring& backup_registry_key,
                                 const base::FilePath& user_data_dir,
                                 PrefService* local_state)
    :{}

void CleanExitBeacon::Initialize() {}

bool CleanExitBeacon::DidPreviousSessionExitCleanly(
    base::Value* beacon_file_contents) {}

bool CleanExitBeacon::IsExtendedSafeModeSupported() const {}

void CleanExitBeacon::WriteBeaconValue(bool exited_cleanly,
                                       bool is_extended_safe_mode) {}

#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_IOS)
std::optional<bool> CleanExitBeacon::ExitedCleanly() {
#if BUILDFLAG(IS_WIN)
  base::win::RegKey regkey;
  DWORD value = 0u;
  if (regkey.Open(HKEY_CURRENT_USER, backup_registry_key_.c_str(),
                  KEY_ALL_ACCESS) == ERROR_SUCCESS &&
      regkey.ReadValueDW(
          base::ASCIIToWide(prefs::kStabilityExitedCleanly).c_str(), &value) ==
          ERROR_SUCCESS) {
    return value ? true : false;
  }
  return std::nullopt;
#endif  // BUILDFLAG(IS_WIN)
#if BUILDFLAG(IS_IOS)
  if (HasUserDefaultsBeacon())
    return GetUserDefaultsBeacon();
  return std::nullopt;
#endif  // BUILDFLAG(IS_IOS)
}
#endif  // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_IOS)

void CleanExitBeacon::UpdateLastLiveTimestamp() {}

const base::FilePath CleanExitBeacon::GetUserDataDirForTesting() const {}

base::FilePath CleanExitBeacon::GetBeaconFilePathForTesting() const {}

// static
void CleanExitBeacon::RegisterPrefs(PrefRegistrySimple* registry) {}

// static
void CleanExitBeacon::EnsureCleanShutdown(PrefService* local_state) {}

// static
void CleanExitBeacon::SetStabilityExitedCleanlyForTesting(
    PrefService* local_state,
    bool exited_cleanly) {}

// static
std::string CleanExitBeacon::CreateBeaconFileContentsForTesting(
    bool exited_cleanly,
    int crash_streak) {}

// static
void CleanExitBeacon::ResetStabilityExitedCleanlyForTesting(
    PrefService* local_state) {}

// static
void CleanExitBeacon::SkipCleanShutdownStepsForTesting() {}

bool CleanExitBeacon::IsBeaconFileSupported() const {}

void CleanExitBeacon::WriteBeaconFile(bool exited_cleanly) const {}

}  // namespace metrics