1 // Copyright (c) 2012 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 5 #ifndef CHROME_BROWSER_CHROMEOS_BOOT_TIMES_LOADER_H_ 6 #define CHROME_BROWSER_CHROMEOS_BOOT_TIMES_LOADER_H_ 7 8 #include <set> 9 #include <string> 10 11 #include "base/atomic_sequence_num.h" 12 #include "base/callback_forward.h" 13 #include "base/compiler_specific.h" 14 #include "base/task/cancelable_task_tracker.h" 15 #include "base/time/time.h" 16 #include "content/public/browser/notification_observer.h" 17 #include "content/public/browser/notification_registrar.h" 18 #include "content/public/browser/render_widget_host.h" 19 20 class PrefService; 21 22 namespace chromeos { 23 24 // BootTimesLoader loads the bootimes of Chrome OS from the file system. 25 // Loading is done asynchronously on the file thread. Once loaded, 26 // BootTimesLoader calls back to a method of your choice with the boot times. 27 // To use BootTimesLoader, do the following: 28 // 29 // . In your class define a member field of type chromeos::BootTimesLoader and 30 // base::CancelableTaskTracker. 31 // . Define the callback method, something like: 32 // void OnBootTimesLoaded(const BootTimesLoader::BootTimes& boot_times); 33 // . When you want the version invoke: loader.GetBootTimes(callback, &tracker_); 34 class BootTimesLoader : public content::NotificationObserver { 35 public: 36 BootTimesLoader(); 37 virtual ~BootTimesLoader(); 38 39 static BootTimesLoader* Get(); 40 41 // Add a time marker for login. A timeline will be dumped to 42 // /tmp/login-times-sent after login is done. If |send_to_uma| is true 43 // the time between this marker and the last will be sent to UMA with 44 // the identifier BootTime.|marker_name|. 45 void AddLoginTimeMarker(const std::string& marker_name, bool send_to_uma); 46 47 // Add a time marker for logout. A timeline will be dumped to 48 // /tmp/logout-times-sent after logout is done. If |send_to_uma| is true 49 // the time between this marker and the last will be sent to UMA with 50 // the identifier ShutdownTime.|marker_name|. 51 void AddLogoutTimeMarker(const std::string& marker_name, bool send_to_uma); 52 53 // Records current uptime and disk usage for metrics use. 54 // Posts task to file thread. 55 // name will be used as part of file names in /tmp. 56 // Existing stats files will not be overwritten. 57 void RecordCurrentStats(const std::string& name); 58 59 // Saves away the stats at main, so the can be recorded later. At main() time 60 // the necessary threads don't exist yet for recording the data. 61 void SaveChromeMainStats(); 62 63 // Records the data previously saved by SaveChromeMainStats(), using the 64 // file thread. Existing stats files will not be overwritten. 65 void RecordChromeMainStats(); 66 67 // Records the time that a login was attempted. This will overwrite any 68 // previous login attempt times. 69 void RecordLoginAttempted(); 70 71 // content::NotificationObserver implementation. 72 virtual void Observe(int type, 73 const content::NotificationSource& source, 74 const content::NotificationDetails& details) OVERRIDE; 75 76 // Records "LoginDone" event. 77 void LoginDone(bool is_user_new); 78 79 // Writes the logout times to a /tmp/logout-times-sent. Unlike login 80 // times, we manually call this function for logout times, as we cannot 81 // rely on notification service to tell when the logout is done. 82 void WriteLogoutTimes(); 83 84 // Mark that WriteLogoutTimes should handle restart. 85 void set_restart_requested() { restart_requested_ = true; } 86 87 // This is called on Chrome process startup to write saved logout stats. 88 void OnChromeProcessStart(); 89 90 // This saves logout-started metric to Local State. 91 void OnLogoutStarted(PrefService* state); 92 93 private: 94 // BootTimesLoader calls into the Backend on the file thread to load 95 // the boot times. 96 class Backend : public base::RefCountedThreadSafe<Backend> { 97 public: 98 Backend() {} 99 100 private: 101 friend class base::RefCountedThreadSafe<Backend>; 102 103 ~Backend() {} 104 105 DISALLOW_COPY_AND_ASSIGN(Backend); 106 }; 107 108 class TimeMarker { 109 public: 110 TimeMarker(const std::string& name, bool send_to_uma) 111 : name_(name), 112 time_(base::Time::NowFromSystemTime()), 113 send_to_uma_(send_to_uma) {} 114 std::string name() const { return name_; } 115 base::Time time() const { return time_; } 116 bool send_to_uma() const { return send_to_uma_; } 117 118 // comparitor for sorting 119 bool operator<(const TimeMarker& other) const { 120 return time_ < other.time_; 121 } 122 123 private: 124 friend class std::vector<TimeMarker>; 125 std::string name_; 126 base::Time time_; 127 bool send_to_uma_; 128 }; 129 130 class Stats { 131 public: 132 // Initializes stats with current /proc values. 133 static Stats GetCurrentStats(); 134 135 // Returns JSON representation. 136 std::string SerializeToString() const; 137 138 // Creates new object from JSON representation. 139 static Stats DeserializeFromString(const std::string& value); 140 141 const std::string& uptime() const { return uptime_; } 142 const std::string& disk() const { return disk_; } 143 144 // Writes "uptime in seconds" to result. (This is first field in uptime_.) 145 // Returns true on successful conversion. 146 bool UptimeDouble(double* result) const; 147 148 void RecordStats(const std::string& name) const; 149 void RecordStatsWithCallback(const std::string& name, 150 const base::Closure& callback) const; 151 152 private: 153 // Runs on BlockingPool 154 void RecordStatsImpl(const std::string& name) const; 155 156 std::string uptime_; 157 std::string disk_; 158 }; 159 160 static void WriteTimes(const std::string base_name, 161 const std::string uma_name, 162 const std::string uma_prefix, 163 std::vector<TimeMarker> login_times); 164 static void AddMarker(std::vector<TimeMarker>* vector, TimeMarker marker); 165 166 // Clear saved logout-started metric in Local State. 167 // This method is called when logout-state was writen to file. 168 static void ClearLogoutStartedLastPreference(); 169 170 // Used to hold the stats at main(). 171 Stats chrome_main_stats_; 172 scoped_refptr<Backend> backend_; 173 174 // Used to track notifications for login. 175 content::NotificationRegistrar registrar_; 176 base::AtomicSequenceNumber num_tabs_; 177 bool have_registered_; 178 179 std::vector<TimeMarker> login_time_markers_; 180 std::vector<TimeMarker> logout_time_markers_; 181 std::set<content::RenderWidgetHost*> render_widget_hosts_loading_; 182 183 bool login_done_; 184 185 bool restart_requested_; 186 187 DISALLOW_COPY_AND_ASSIGN(BootTimesLoader); 188 }; 189 190 } // namespace chromeos 191 192 #endif // CHROME_BROWSER_CHROMEOS_BOOT_TIMES_LOADER_H_ 193