#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;
bool g_skip_clean_shutdown_steps = …;
#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_IOS)
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
void MaybeIncrementCrashStreak(bool did_previous_session_exit_cleanly,
base::Value* beacon_file_contents,
PrefService* local_state) { … }
void RecordBeaconFileState(BeaconFileState file_state) { … }
std::unique_ptr<base::Value> MaybeGetFileContents(
const base::FilePath& beacon_file_path) { … }
}
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
#if BUILDFLAG(IS_IOS)
if (HasUserDefaultsBeacon())
return GetUserDefaultsBeacon();
return std::nullopt;
#endif
}
#endif
void CleanExitBeacon::UpdateLastLiveTimestamp() { … }
const base::FilePath CleanExitBeacon::GetUserDataDirForTesting() const { … }
base::FilePath CleanExitBeacon::GetBeaconFilePathForTesting() const { … }
void CleanExitBeacon::RegisterPrefs(PrefRegistrySimple* registry) { … }
void CleanExitBeacon::EnsureCleanShutdown(PrefService* local_state) { … }
void CleanExitBeacon::SetStabilityExitedCleanlyForTesting(
PrefService* local_state,
bool exited_cleanly) { … }
std::string CleanExitBeacon::CreateBeaconFileContentsForTesting(
bool exited_cleanly,
int crash_streak) { … }
void CleanExitBeacon::ResetStabilityExitedCleanlyForTesting(
PrefService* local_state) { … }
void CleanExitBeacon::SkipCleanShutdownStepsForTesting() { … }
bool CleanExitBeacon::IsBeaconFileSupported() const { … }
void CleanExitBeacon::WriteBeaconFile(bool exited_cleanly) const { … }
}