clean_exit_beacon.h 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. // Copyright 2014 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #ifndef COMPONENTS_METRICS_CLEAN_EXIT_BEACON_H_
  5. #define COMPONENTS_METRICS_CLEAN_EXIT_BEACON_H_
  6. #include <string>
  7. #include "base/files/file_path.h"
  8. #include "base/memory/raw_ptr.h"
  9. #include "base/time/time.h"
  10. #include "base/values.h"
  11. #include "build/build_config.h"
  12. #include "third_party/abseil-cpp/absl/types/optional.h"
  13. class PrefRegistrySimple;
  14. class PrefService;
  15. namespace metrics {
  16. // The name of the beacon file, which is relative to the user data directory
  17. // and used to store the CleanExitBeacon value and the variations crash streak.
  18. extern const base::FilePath::CharType kCleanExitBeaconFilename[];
  19. // Captures all possible beacon value permutations for two distinct beacons.
  20. // Exposed for testing.
  21. //
  22. // These values are persisted to logs. Entries should not be renumbered and
  23. // numeric values should never be reused.
  24. enum class CleanExitBeaconConsistency {
  25. kCleanClean = 0,
  26. kCleanDirty = 1,
  27. kCleanMissing = 2,
  28. kDirtyClean = 3,
  29. kDirtyDirty = 4,
  30. kDirtyMissing = 5,
  31. kMissingClean = 6,
  32. kMissingDirty = 7,
  33. kMissingMissing = 8,
  34. kMaxValue = kMissingMissing,
  35. };
  36. // Denotes the state of the beacon file. Exposed for testing.
  37. //
  38. // These values are persisted to logs. Entries should not be renumbered and
  39. // numeric values should never be reused.
  40. enum class BeaconFileState {
  41. kReadable = 0,
  42. kNotDeserializable = 1,
  43. kMissingDictionary = 2,
  44. kMissingCrashStreak = 3,
  45. kMissingBeacon = 4,
  46. kMaxValue = kMissingBeacon,
  47. };
  48. // Reads and updates a beacon used to detect whether the previous browser
  49. // process exited cleanly.
  50. class CleanExitBeacon {
  51. public:
  52. // Instantiates a CleanExitBeacon whose value is stored in
  53. // |has_exited_cleanly_|. The value is persisted in the beacon file on
  54. // platforms that support this mechanism and in Local State on platforms that
  55. // don't.
  56. //
  57. // On Windows, |backup_registry_key| stores a backup of the beacon to verify
  58. // that the pref's value corresponds to the registry's. |backup_registry_key|
  59. // is ignored on other platforms, but iOS has a similar verification
  60. // mechanism embedded inside CleanExitBeacon.
  61. //
  62. // |user_data_dir| is the path to the client's user data directory. If empty,
  63. // the beacon file is not used.
  64. CleanExitBeacon(const std::wstring& backup_registry_key,
  65. const base::FilePath& user_data_dir,
  66. PrefService* local_state);
  67. virtual ~CleanExitBeacon() = default;
  68. // Not copyable or movable.
  69. CleanExitBeacon(const CleanExitBeacon&) = delete;
  70. CleanExitBeacon& operator=(const CleanExitBeacon&) = delete;
  71. // Initializes the CleanExitBeacon. This includes the following tasks:
  72. // 1. Determining if the last session exited cleanly,
  73. // 2. Incrementing the crash streak, if necessary, and
  74. // 3. Emitting some metrics.
  75. void Initialize();
  76. // Returns the original value of the beacon.
  77. bool exited_cleanly() const { return did_previous_session_exit_cleanly_; }
  78. // Returns the original value of the last live timestamp.
  79. base::Time browser_last_live_timestamp() const {
  80. return initial_browser_last_live_timestamp_;
  81. }
  82. // Returns true if Extended Variations Safe Mode is supported on this
  83. // platform. Android WebLayer and WebView do not support this.
  84. bool IsExtendedSafeModeSupported() const;
  85. // Sets the beacon value to |exited_cleanly| and writes the value to disk if
  86. // the current value (see has_exited_cleanly_) is not already
  87. // |exited_cleanly|. Note that on platforms that do not support the beacon
  88. // file, the write is scheduled, so the value may not be persisted if the
  89. // browser process crashes.
  90. //
  91. // Also, updates the last live timestamp.
  92. //
  93. // |is_extended_safe_mode| denotes whether Chrome is about to start watching
  94. // for browser crashes early on in startup as a part of Extended Variations
  95. // Safe Mode, which is supported by most, but not all, platforms.
  96. //
  97. // TODO(crbug/1341125): Consider removing |is_extended_safe_mode|.
  98. void WriteBeaconValue(bool exited_cleanly,
  99. bool is_extended_safe_mode = false);
  100. // Updates the last live timestamp.
  101. void UpdateLastLiveTimestamp();
  102. const base::FilePath GetUserDataDirForTesting() const;
  103. base::FilePath GetBeaconFilePathForTesting() const;
  104. // Registers local state prefs used by this class.
  105. static void RegisterPrefs(PrefRegistrySimple* registry);
  106. // Updates both Local State and NSUserDefaults beacon values.
  107. static void SetStabilityExitedCleanlyForTesting(PrefService* local_state,
  108. bool exited_cleanly);
  109. // Creates and returns a well-formed beacon file contents with the given
  110. // values.
  111. static std::string CreateBeaconFileContentsForTesting(bool exited_cleanly,
  112. int crash_streak);
  113. // Resets both Local State and NSUserDefaults beacon values.
  114. static void ResetStabilityExitedCleanlyForTesting(PrefService* local_state);
  115. // CHECKs that Chrome exited cleanly.
  116. static void EnsureCleanShutdown(PrefService* local_state);
  117. #if BUILDFLAG(IS_IOS)
  118. // Sets the NSUserDefaults beacon value.
  119. static void SetUserDefaultsBeacon(bool exited_cleanly);
  120. // Checks user default value of kUseUserDefaultsForExitedCleanlyBeacon.
  121. // Because variations are not initialized early in startup, pair a user
  122. // defaults value with the variations config.
  123. static bool ShouldUseUserDefaultsBeacon();
  124. // Syncs feature kUseUserDefaultsForExitedCleanlyBeacon to NSUserDefaults
  125. // kUserDefaultsFeatureFlagForExitedCleanlyBeacon.
  126. static void SyncUseUserDefaultsBeacon();
  127. #endif // BUILDFLAG(IS_IOS)
  128. // Prevents a test browser from performing two clean shutdown steps. First, it
  129. // prevents the beacon value from being updated after this function is called.
  130. // This prevents the the test browser from signaling that Chrome is shutting
  131. // down cleanly. Second, it makes EnsureCleanShutdown() a no-op.
  132. static void SkipCleanShutdownStepsForTesting();
  133. private:
  134. // Returns true if the previous session exited cleanly. Either Local State
  135. // or |beacon_file_contents| is used to get this information. Which is used
  136. // depends on the client's platform and the existence of a valid beacon file.
  137. // Also, records several metrics.
  138. //
  139. // Should be called only once: at startup.
  140. bool DidPreviousSessionExitCleanly(base::Value* beacon_file_contents);
  141. // Returns true if the beacon file is supported on this platform. Android
  142. // WebLayer and WebView do not support this.
  143. bool IsBeaconFileSupported() const;
  144. // Writes |exited_cleanly| and the crash streak to the file located at
  145. // |beacon_file_path_|.
  146. void WriteBeaconFile(bool exited_cleanly) const;
  147. #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_IOS)
  148. // Returns whether Chrome exited cleanly in the previous session according to
  149. // the platform-specific beacon (the registry for Windows or NSUserDefaults
  150. // for iOS). Returns absl::nullopt if the platform-specific location does not
  151. // have beacon info.
  152. absl::optional<bool> ExitedCleanly();
  153. #endif // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_IOS)
  154. #if BUILDFLAG(IS_IOS)
  155. // Returns true if the NSUserDefaults beacon value is set.
  156. static bool HasUserDefaultsBeacon();
  157. // Returns the NSUserDefaults beacon value.
  158. static bool GetUserDefaultsBeacon();
  159. // Clears the NSUserDefaults beacon value.
  160. static void ResetUserDefaultsBeacon();
  161. #endif // BUILDFLAG(IS_IOS)
  162. // Indicates whether the CleanExitBeacon has been initialized.
  163. bool initialized_ = false;
  164. // Stores a backup of the beacon. Windows only.
  165. const std::wstring backup_registry_key_;
  166. // Path to the client's user data directory. May be empty.
  167. const base::FilePath user_data_dir_;
  168. const raw_ptr<PrefService> local_state_;
  169. // This is the value of the last live timestamp from local state at the time
  170. // of construction. It is a timestamp from the previous browser session when
  171. // the browser was known to be alive.
  172. const base::Time initial_browser_last_live_timestamp_;
  173. bool did_previous_session_exit_cleanly_ = false;
  174. // Denotes the current beacon value for this session, which is updated via
  175. // CleanExitBeacon::WriteBeaconValue(). When `false`, Chrome is watching for
  176. // browser crashes. When `true`, Chrome has stopped watching for crashes. When
  177. // unset, Chrome has neither started nor stopped watching for crashes.
  178. absl::optional<bool> has_exited_cleanly_ = absl::nullopt;
  179. // Where the clean exit beacon and the variations crash streak are stored on
  180. // platforms that support the beacon file.
  181. base::FilePath beacon_file_path_;
  182. };
  183. } // namespace metrics
  184. #endif // COMPONENTS_METRICS_CLEAN_EXIT_BEACON_H_