229 lines
8.6 KiB
C++
229 lines
8.6 KiB
C++
// 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.
|
|
|
|
#ifndef COMPONENTS_METRICS_CLEAN_EXIT_BEACON_H_
|
|
#define COMPONENTS_METRICS_CLEAN_EXIT_BEACON_H_
|
|
|
|
#include <string>
|
|
|
|
#include "base/files/file_path.h"
|
|
#include "base/memory/raw_ptr.h"
|
|
#include "base/time/time.h"
|
|
#include "base/values.h"
|
|
#include "build/build_config.h"
|
|
#include "third_party/abseil-cpp/absl/types/optional.h"
|
|
|
|
class PrefRegistrySimple;
|
|
class PrefService;
|
|
|
|
namespace metrics {
|
|
|
|
// The name of the beacon file, which is relative to the user data directory
|
|
// and used to store the CleanExitBeacon value and the variations crash streak.
|
|
extern const base::FilePath::CharType kCleanExitBeaconFilename[];
|
|
|
|
// Captures all possible beacon value permutations for two distinct beacons.
|
|
// Exposed for testing.
|
|
//
|
|
// These values are persisted to logs. Entries should not be renumbered and
|
|
// numeric values should never be reused.
|
|
enum class CleanExitBeaconConsistency {
|
|
kCleanClean = 0,
|
|
kCleanDirty = 1,
|
|
kCleanMissing = 2,
|
|
kDirtyClean = 3,
|
|
kDirtyDirty = 4,
|
|
kDirtyMissing = 5,
|
|
kMissingClean = 6,
|
|
kMissingDirty = 7,
|
|
kMissingMissing = 8,
|
|
kMaxValue = kMissingMissing,
|
|
};
|
|
|
|
// Denotes the state of the beacon file. Exposed for testing.
|
|
//
|
|
// These values are persisted to logs. Entries should not be renumbered and
|
|
// numeric values should never be reused.
|
|
enum class BeaconFileState {
|
|
kReadable = 0,
|
|
kNotDeserializable = 1,
|
|
kMissingDictionary = 2,
|
|
kMissingCrashStreak = 3,
|
|
kMissingBeacon = 4,
|
|
kMaxValue = kMissingBeacon,
|
|
};
|
|
|
|
// Reads and updates a beacon used to detect whether the previous browser
|
|
// process exited cleanly.
|
|
class CleanExitBeacon {
|
|
public:
|
|
// Instantiates a CleanExitBeacon whose value is stored in
|
|
// |has_exited_cleanly_|. The value is persisted in the beacon file on
|
|
// platforms that support this mechanism and in Local State on platforms that
|
|
// don't.
|
|
//
|
|
// On Windows, |backup_registry_key| stores a backup of the beacon to verify
|
|
// that the pref's value corresponds to the registry's. |backup_registry_key|
|
|
// is ignored on other platforms, but iOS has a similar verification
|
|
// mechanism embedded inside CleanExitBeacon.
|
|
//
|
|
// |user_data_dir| is the path to the client's user data directory. If empty,
|
|
// the beacon file is not used.
|
|
CleanExitBeacon(const std::wstring& backup_registry_key,
|
|
const base::FilePath& user_data_dir,
|
|
PrefService* local_state);
|
|
|
|
virtual ~CleanExitBeacon() = default;
|
|
|
|
// Not copyable or movable.
|
|
CleanExitBeacon(const CleanExitBeacon&) = delete;
|
|
CleanExitBeacon& operator=(const CleanExitBeacon&) = delete;
|
|
|
|
// Initializes the CleanExitBeacon. This includes the following tasks:
|
|
// 1. Determining if the last session exited cleanly,
|
|
// 2. Incrementing the crash streak, if necessary, and
|
|
// 3. Emitting some metrics.
|
|
void Initialize();
|
|
|
|
// Returns the original value of the beacon.
|
|
bool exited_cleanly() const { return did_previous_session_exit_cleanly_; }
|
|
|
|
// Returns the original value of the last live timestamp.
|
|
base::Time browser_last_live_timestamp() const {
|
|
return initial_browser_last_live_timestamp_;
|
|
}
|
|
|
|
// Returns true if Extended Variations Safe Mode is supported on this
|
|
// platform. Android WebLayer and WebView do not support this.
|
|
bool IsExtendedSafeModeSupported() const;
|
|
|
|
// Sets the beacon value to |exited_cleanly| and writes the value to disk if
|
|
// the current value (see has_exited_cleanly_) is not already
|
|
// |exited_cleanly|. Note that on platforms that do not support the beacon
|
|
// file, the write is scheduled, so the value may not be persisted if the
|
|
// browser process crashes.
|
|
//
|
|
// Also, updates the last live timestamp.
|
|
//
|
|
// |is_extended_safe_mode| denotes whether Chrome is about to start watching
|
|
// for browser crashes early on in startup as a part of Extended Variations
|
|
// Safe Mode, which is supported by most, but not all, platforms.
|
|
//
|
|
// TODO(crbug/1341125): Consider removing |is_extended_safe_mode|.
|
|
void WriteBeaconValue(bool exited_cleanly,
|
|
bool is_extended_safe_mode = false);
|
|
|
|
// Updates the last live timestamp.
|
|
void UpdateLastLiveTimestamp();
|
|
|
|
const base::FilePath GetUserDataDirForTesting() const;
|
|
base::FilePath GetBeaconFilePathForTesting() const;
|
|
|
|
// Registers local state prefs used by this class.
|
|
static void RegisterPrefs(PrefRegistrySimple* registry);
|
|
|
|
// Updates both Local State and NSUserDefaults beacon values.
|
|
static void SetStabilityExitedCleanlyForTesting(PrefService* local_state,
|
|
bool exited_cleanly);
|
|
|
|
// Creates and returns a well-formed beacon file contents with the given
|
|
// values.
|
|
static std::string CreateBeaconFileContentsForTesting(bool exited_cleanly,
|
|
int crash_streak);
|
|
|
|
// Resets both Local State and NSUserDefaults beacon values.
|
|
static void ResetStabilityExitedCleanlyForTesting(PrefService* local_state);
|
|
|
|
// CHECKs that Chrome exited cleanly.
|
|
static void EnsureCleanShutdown(PrefService* local_state);
|
|
|
|
#if BUILDFLAG(IS_IOS)
|
|
// Sets the NSUserDefaults beacon value.
|
|
static void SetUserDefaultsBeacon(bool exited_cleanly);
|
|
|
|
// Checks user default value of kUseUserDefaultsForExitedCleanlyBeacon.
|
|
// Because variations are not initialized early in startup, pair a user
|
|
// defaults value with the variations config.
|
|
static bool ShouldUseUserDefaultsBeacon();
|
|
|
|
// Syncs feature kUseUserDefaultsForExitedCleanlyBeacon to NSUserDefaults
|
|
// kUserDefaultsFeatureFlagForExitedCleanlyBeacon.
|
|
static void SyncUseUserDefaultsBeacon();
|
|
#endif // BUILDFLAG(IS_IOS)
|
|
|
|
// Prevents a test browser from performing two clean shutdown steps. First, it
|
|
// prevents the beacon value from being updated after this function is called.
|
|
// This prevents the the test browser from signaling that Chrome is shutting
|
|
// down cleanly. Second, it makes EnsureCleanShutdown() a no-op.
|
|
static void SkipCleanShutdownStepsForTesting();
|
|
|
|
private:
|
|
// Returns true if the previous session exited cleanly. Either Local State
|
|
// or |beacon_file_contents| is used to get this information. Which is used
|
|
// depends on the client's platform and the existence of a valid beacon file.
|
|
// Also, records several metrics.
|
|
//
|
|
// Should be called only once: at startup.
|
|
bool DidPreviousSessionExitCleanly(base::Value* beacon_file_contents);
|
|
|
|
// Returns true if the beacon file is supported on this platform. Android
|
|
// WebLayer and WebView do not support this.
|
|
bool IsBeaconFileSupported() const;
|
|
|
|
// Writes |exited_cleanly| and the crash streak to the file located at
|
|
// |beacon_file_path_|.
|
|
void WriteBeaconFile(bool exited_cleanly) const;
|
|
|
|
#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_IOS)
|
|
// Returns whether Chrome exited cleanly in the previous session according to
|
|
// the platform-specific beacon (the registry for Windows or NSUserDefaults
|
|
// for iOS). Returns absl::nullopt if the platform-specific location does not
|
|
// have beacon info.
|
|
absl::optional<bool> ExitedCleanly();
|
|
#endif // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_IOS)
|
|
|
|
#if BUILDFLAG(IS_IOS)
|
|
// Returns true if the NSUserDefaults beacon value is set.
|
|
static bool HasUserDefaultsBeacon();
|
|
|
|
// Returns the NSUserDefaults beacon value.
|
|
static bool GetUserDefaultsBeacon();
|
|
|
|
// Clears the NSUserDefaults beacon value.
|
|
static void ResetUserDefaultsBeacon();
|
|
#endif // BUILDFLAG(IS_IOS)
|
|
|
|
// Indicates whether the CleanExitBeacon has been initialized.
|
|
bool initialized_ = false;
|
|
|
|
// Stores a backup of the beacon. Windows only.
|
|
const std::wstring backup_registry_key_;
|
|
|
|
// Path to the client's user data directory. May be empty.
|
|
const base::FilePath user_data_dir_;
|
|
|
|
const raw_ptr<PrefService> local_state_;
|
|
|
|
// This is the value of the last live timestamp from local state at the time
|
|
// of construction. It is a timestamp from the previous browser session when
|
|
// the browser was known to be alive.
|
|
const base::Time initial_browser_last_live_timestamp_;
|
|
|
|
bool did_previous_session_exit_cleanly_ = false;
|
|
|
|
// Denotes the current beacon value for this session, which is updated via
|
|
// CleanExitBeacon::WriteBeaconValue(). When `false`, Chrome is watching for
|
|
// browser crashes. When `true`, Chrome has stopped watching for crashes. When
|
|
// unset, Chrome has neither started nor stopped watching for crashes.
|
|
absl::optional<bool> has_exited_cleanly_ = absl::nullopt;
|
|
|
|
// Where the clean exit beacon and the variations crash streak are stored on
|
|
// platforms that support the beacon file.
|
|
base::FilePath beacon_file_path_;
|
|
};
|
|
|
|
} // namespace metrics
|
|
|
|
#endif // COMPONENTS_METRICS_CLEAN_EXIT_BEACON_H_
|