1// Copyright (c) 2011 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#pragma once
8
9#include <string>
10
11#include "base/atomic_sequence_num.h"
12#include "base/callback.h"
13#include "base/time.h"
14#include "content/browser/cancelable_request.h"
15#include "content/common/notification_observer.h"
16#include "content/common/notification_registrar.h"
17
18namespace chromeos {
19
20// BootTimesLoader loads the bootimes of Chrome OS from the file system.
21// Loading is done asynchronously on the file thread. Once loaded,
22// BootTimesLoader calls back to a method of your choice with the boot times.
23// To use BootTimesLoader do the following:
24//
25// . In your class define a member field of type chromeos::BootTimesLoader and
26//   CancelableRequestConsumerBase.
27// . Define the callback method, something like:
28//   void OnBootTimesLoader(chromeos::BootTimesLoader::Handle,
29//                             BootTimesLoader::BootTimes boot_times);
30// . When you want the version invoke: loader.GetBootTimes(&consumer, callback);
31class BootTimesLoader
32    : public CancelableRequestProvider,
33      public NotificationObserver {
34 public:
35  BootTimesLoader();
36
37  // All fields are 0.0 if they couldn't be found.
38  typedef struct BootTimes {
39    double firmware;           // Time from power button to kernel being loaded.
40    double pre_startup;        // Time from kernel to system code being called.
41    double x_started;          // Time X server is ready to be connected to.
42    double chrome_exec;        // Time session manager executed Chrome.
43    double chrome_main;        // Time chrome's main() was called.
44    double login_prompt_ready; // Time login (or OOB) panel is displayed.
45    double system;             // Time system took to start chrome.
46    double chrome;             // Time chrome took to display login panel.
47    double total;              // Time from power button to login panel.
48
49    BootTimes() : firmware(0),
50                  pre_startup(0),
51                  x_started(0),
52                  chrome_exec(0),
53                  chrome_main(0),
54                  login_prompt_ready(0),
55                  system(0),
56                  chrome(0),
57                  total(0) {}
58  } BootTimes;
59
60  // Signature
61  typedef Callback2<Handle, BootTimes>::Type GetBootTimesCallback;
62
63  typedef CancelableRequest<GetBootTimesCallback> GetBootTimesRequest;
64
65  static BootTimesLoader* Get();
66
67  // Asynchronously requests the info.
68  Handle GetBootTimes(
69      CancelableRequestConsumerBase* consumer,
70      GetBootTimesCallback* callback);
71
72  // Add a time marker for login. A timeline will be dumped to
73  // /tmp/login-times-sent after login is done. If |send_to_uma| is true
74  // the time between this marker and the last will be sent to UMA with
75  // the identifier BootTime.|marker_name|.
76  void AddLoginTimeMarker(const std::string& marker_name, bool send_to_uma);
77
78  // Add a time marker for logout. A timeline will be dumped to
79  // /tmp/logout-times-sent after logout is done. If |send_to_uma| is true
80  // the time between this marker and the last will be sent to UMA with
81  // the identifier ShutdownTime.|marker_name|.
82  void AddLogoutTimeMarker(const std::string& marker_name, bool send_to_uma);
83
84  // Records current uptime and disk usage for metrics use.
85  // Posts task to file thread.
86  // name will be used as part of file names in /tmp.
87  // Existing stats files will not be overwritten.
88  void RecordCurrentStats(const std::string& name);
89
90  // Saves away the stats at main, so the can be recorded later. At main() time
91  // the necessary threads don't exist yet for recording the data.
92  void SaveChromeMainStats();
93
94  // Records the data previously saved by SaveChromeMainStats(), using the
95  // file thread. Existing stats files will not be overwritten.
96  void RecordChromeMainStats();
97
98  // Records the time that a login was attempted. This will overwrite any
99  // previous login attempt times.
100  void RecordLoginAttempted();
101
102  // NotificationObserver implementation.
103  virtual void Observe(NotificationType type,
104                       const NotificationSource& source,
105                       const NotificationDetails& details);
106
107  // Writes the logout times to a /tmp/logout-times-sent. Unlike login
108  // times, we manually call this function for logout times, as we cannot
109  // rely on notification service to tell when the logout is done.
110  void WriteLogoutTimes();
111
112 private:
113  // BootTimesLoader calls into the Backend on the file thread to load
114  // the boot times.
115  class Backend : public base::RefCountedThreadSafe<Backend> {
116   public:
117    Backend() {}
118
119    void GetBootTimes(scoped_refptr<GetBootTimesRequest> request);
120
121   private:
122    friend class base::RefCountedThreadSafe<Backend>;
123
124    ~Backend() {}
125
126    DISALLOW_COPY_AND_ASSIGN(Backend);
127  };
128
129  class TimeMarker {
130   public:
131    TimeMarker(const std::string& name, bool send_to_uma)
132        : name_(name),
133          time_(base::Time::NowFromSystemTime()),
134          send_to_uma_(send_to_uma) {}
135    std::string name() const { return name_; }
136    base::Time time() const { return time_; }
137    bool send_to_uma() const { return send_to_uma_; }
138
139   private:
140    friend class std::vector<TimeMarker>;
141    std::string name_;
142    base::Time time_;
143    bool send_to_uma_;
144  };
145
146  struct Stats {
147   public:
148    std::string uptime;
149    std::string disk;
150  };
151
152  static void RecordStats(
153      const std::string& name, const Stats& stats);
154  static Stats GetCurrentStats();
155  static void WriteTimes(const std::string base_name,
156                         const std::string uma_name,
157                         const std::string uma_prefix,
158                         const std::vector<TimeMarker> login_times);
159
160  // Used to hold the stats at main().
161  Stats chrome_main_stats_;
162  scoped_refptr<Backend> backend_;
163
164  // Used to track notifications for login.
165  NotificationRegistrar registrar_;
166  base::AtomicSequenceNumber num_tabs_;
167  bool have_registered_;
168
169  std::vector<TimeMarker> login_time_markers_;
170  std::vector<TimeMarker> logout_time_markers_;
171
172  DISALLOW_COPY_AND_ASSIGN(BootTimesLoader);
173};
174
175}  // namespace chromeos
176
177#endif  // CHROME_BROWSER_CHROMEOS_BOOT_TIMES_LOADER_H_
178