15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef CHROME_BROWSER_CHROMEOS_BOOT_TIMES_LOADER_H_
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define CHROME_BROWSER_CHROMEOS_BOOT_TIMES_LOADER_H_
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <set>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/atomic_sequence_num.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/callback_forward.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/compiler_specific.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/task/cancelable_task_tracker.h"
151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/time/time.h"
161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chromeos/login_event_recorder.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_observer.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_registrar.h"
19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "content/public/browser/render_widget_host.h"
20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class PrefService;
22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace chromeos {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// BootTimesLoader loads the bootimes of Chrome OS from the file system.
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Loading is done asynchronously on the file thread. Once loaded,
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// BootTimesLoader calls back to a method of your choice with the boot times.
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// To use BootTimesLoader, do the following:
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// . In your class define a member field of type chromeos::BootTimesLoader and
317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch//   base::CancelableTaskTracker.
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// . Define the callback method, something like:
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   void OnBootTimesLoaded(const BootTimesLoader::BootTimes& boot_times);
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// . When you want the version invoke: loader.GetBootTimes(callback, &tracker_);
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BootTimesLoader : public content::NotificationObserver,
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        public LoginEventRecorder::Delegate {
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BootTimesLoader();
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~BootTimesLoader();
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static BootTimesLoader* Get();
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // LoginEventRecorder::Delegate override.
445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual void AddLoginTimeMarker(const std::string& marker_name,
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  bool send_to_uma) OVERRIDE;
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void RecordAuthenticationSuccess() OVERRIDE;
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void RecordAuthenticationFailure() OVERRIDE;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Add a time marker for logout. A timeline will be dumped to
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // /tmp/logout-times-sent after logout is done. If |send_to_uma| is true
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the time between this marker and the last will be sent to UMA with
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the identifier ShutdownTime.|marker_name|.
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void AddLogoutTimeMarker(const std::string& marker_name, bool send_to_uma);
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Records current uptime and disk usage for metrics use.
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Posts task to file thread.
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // name will be used as part of file names in /tmp.
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Existing stats files will not be overwritten.
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void RecordCurrentStats(const std::string& name);
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Saves away the stats at main, so the can be recorded later. At main() time
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the necessary threads don't exist yet for recording the data.
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SaveChromeMainStats();
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Records the data previously saved by SaveChromeMainStats(), using the
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // file thread. Existing stats files will not be overwritten.
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void RecordChromeMainStats();
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Records the time that a login was attempted. This will overwrite any
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // previous login attempt times.
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void RecordLoginAttempted();
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // content::NotificationObserver implementation.
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void Observe(int type,
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const content::NotificationSource& source,
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const content::NotificationDetails& details) OVERRIDE;
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Records "LoginDone" event.
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void LoginDone(bool is_user_new);
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Writes the logout times to a /tmp/logout-times-sent. Unlike login
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // times, we manually call this function for logout times, as we cannot
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // rely on notification service to tell when the logout is done.
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void WriteLogoutTimes();
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
86  // Mark that WriteLogoutTimes should handle restart.
87  void set_restart_requested() { restart_requested_ = true; }
88
89  // This is called on Chrome process startup to write saved logout stats.
90  void OnChromeProcessStart();
91
92  // This saves logout-started metric to Local State.
93  void OnLogoutStarted(PrefService* state);
94
95 private:
96  // BootTimesLoader calls into the Backend on the file thread to load
97  // the boot times.
98  class Backend : public base::RefCountedThreadSafe<Backend> {
99   public:
100    Backend() {}
101
102   private:
103    friend class base::RefCountedThreadSafe<Backend>;
104
105    ~Backend() {}
106
107    DISALLOW_COPY_AND_ASSIGN(Backend);
108  };
109
110  class TimeMarker {
111   public:
112    TimeMarker(const std::string& name, bool send_to_uma)
113        : name_(name),
114          time_(base::Time::NowFromSystemTime()),
115          send_to_uma_(send_to_uma) {}
116    std::string name() const { return name_; }
117    base::Time time() const { return time_; }
118    bool send_to_uma() const { return send_to_uma_; }
119
120    // comparitor for sorting
121    bool operator<(const TimeMarker& other) const {
122      return time_ < other.time_;
123    }
124
125   private:
126    friend class std::vector<TimeMarker>;
127    std::string name_;
128    base::Time time_;
129    bool send_to_uma_;
130  };
131
132  class Stats {
133   public:
134    // Initializes stats with current /proc values.
135    static Stats GetCurrentStats();
136
137    // Returns JSON representation.
138    std::string SerializeToString() const;
139
140    // Creates new object from JSON representation.
141    static Stats DeserializeFromString(const std::string& value);
142
143    const std::string& uptime() const { return uptime_; }
144    const std::string& disk() const { return disk_; }
145
146    // Writes "uptime in seconds" to result. (This is first field in uptime_.)
147    // Returns true on successful conversion.
148    bool UptimeDouble(double* result) const;
149
150    void RecordStats(const std::string& name) const;
151    void RecordStatsWithCallback(const std::string& name,
152                                 const base::Closure& callback) const;
153
154   private:
155    // Runs on BlockingPool
156    void RecordStatsImpl(const std::string& name) const;
157
158    std::string uptime_;
159    std::string disk_;
160  };
161
162  static void WriteTimes(const std::string base_name,
163                         const std::string uma_name,
164                         const std::string uma_prefix,
165                         std::vector<TimeMarker> login_times);
166  static void AddMarker(std::vector<TimeMarker>* vector, TimeMarker marker);
167
168  // Clear saved logout-started metric in Local State.
169  // This method is called when logout-state was writen to file.
170  static void ClearLogoutStartedLastPreference();
171
172  // Used to hold the stats at main().
173  Stats chrome_main_stats_;
174  scoped_refptr<Backend> backend_;
175
176  // Used to track notifications for login.
177  content::NotificationRegistrar registrar_;
178  base::AtomicSequenceNumber num_tabs_;
179  bool have_registered_;
180
181  std::vector<TimeMarker> login_time_markers_;
182  std::vector<TimeMarker> logout_time_markers_;
183  std::set<content::RenderWidgetHost*> render_widget_hosts_loading_;
184
185  bool login_done_;
186
187  bool restart_requested_;
188
189  DISALLOW_COPY_AND_ASSIGN(BootTimesLoader);
190};
191
192}  // namespace chromeos
193
194#endif  // CHROME_BROWSER_CHROMEOS_BOOT_TIMES_LOADER_H_
195