123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228 |
- // Copyright 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.
- #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_
|