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"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h"
145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/task/cancelable_task_tracker.h"
15eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_observer.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_registrar.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/render_widget_host.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)class PrefService;
2146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace chromeos {
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// BootTimesLoader loads the bootimes of Chrome OS from the file system.
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Loading is done asynchronously on the file thread. Once loaded,
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// BootTimesLoader calls back to a method of your choice with the boot times.
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// To use BootTimesLoader, do the following:
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// . In your class define a member field of type chromeos::BootTimesLoader and
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//   base::CancelableTaskTracker.
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// . Define the callback method, something like:
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//   void OnBootTimesLoaded(const BootTimesLoader::BootTimes& boot_times);
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// . When you want the version invoke: loader.GetBootTimes(callback, &tracker_);
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class BootTimesLoader : public content::NotificationObserver {
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BootTimesLoader();
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~BootTimesLoader();
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static BootTimesLoader* Get();
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Add a time marker for login. A timeline will be dumped to
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // /tmp/login-times-sent after login is done. If |send_to_uma| is true
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the time between this marker and the last will be sent to UMA with
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the identifier BootTime.|marker_name|.
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void AddLoginTimeMarker(const std::string& marker_name, bool send_to_uma);
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Add a time marker for logout. A timeline will be dumped to
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // /tmp/logout-times-sent after logout is done. If |send_to_uma| is true
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the time between this marker and the last will be sent to UMA with
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the identifier ShutdownTime.|marker_name|.
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void AddLogoutTimeMarker(const std::string& marker_name, bool send_to_uma);
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Records current uptime and disk usage for metrics use.
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Posts task to file thread.
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // name will be used as part of file names in /tmp.
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Existing stats files will not be overwritten.
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void RecordCurrentStats(const std::string& name);
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Saves away the stats at main, so the can be recorded later. At main() time
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the necessary threads don't exist yet for recording the data.
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SaveChromeMainStats();
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Records the data previously saved by SaveChromeMainStats(), using the
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // file thread. Existing stats files will not be overwritten.
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void RecordChromeMainStats();
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Records the time that a login was attempted. This will overwrite any
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // previous login attempt times.
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void RecordLoginAttempted();
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // content::NotificationObserver implementation.
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void Observe(int type,
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const content::NotificationSource& source,
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const content::NotificationDetails& details) OVERRIDE;
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
76cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Records "LoginDone" event.
77cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  void LoginDone(bool is_user_new);
78cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Writes the logout times to a /tmp/logout-times-sent. Unlike login
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // times, we manually call this function for logout times, as we cannot
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // rely on notification service to tell when the logout is done.
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void WriteLogoutTimes();
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
84cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Mark that WriteLogoutTimes should handle restart.
85cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  void set_restart_requested() { restart_requested_ = true; }
86cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
8746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // This is called on Chrome process startup to write saved logout stats.
8846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  void OnChromeProcessStart();
8946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
9046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // This saves logout-started metric to Local State.
9146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  void OnLogoutStarted(PrefService* state);
9246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // BootTimesLoader calls into the Backend on the file thread to load
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the boot times.
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  class Backend : public base::RefCountedThreadSafe<Backend> {
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   public:
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Backend() {}
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   private:
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    friend class base::RefCountedThreadSafe<Backend>;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ~Backend() {}
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DISALLOW_COPY_AND_ASSIGN(Backend);
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  class TimeMarker {
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   public:
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TimeMarker(const std::string& name, bool send_to_uma)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        : name_(name),
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          time_(base::Time::NowFromSystemTime()),
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          send_to_uma_(send_to_uma) {}
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string name() const { return name_; }
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::Time time() const { return time_; }
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool send_to_uma() const { return send_to_uma_; }
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // comparitor for sorting
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool operator<(const TimeMarker& other) const {
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return time_ < other.time_;
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   private:
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    friend class std::vector<TimeMarker>;
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string name_;
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::Time time_;
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool send_to_uma_;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  class Stats {
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   public:
13246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    // Initializes stats with current /proc values.
13346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    static Stats GetCurrentStats();
13446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
13546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    // Returns JSON representation.
13646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    std::string SerializeToString() const;
13746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
13846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    // Creates new object from JSON representation.
13946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    static Stats DeserializeFromString(const std::string& value);
14046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
14146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const std::string& uptime() const { return uptime_; }
14246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const std::string& disk() const { return disk_; }
14346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
14446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    // Writes "uptime in seconds" to result. (This is first field in uptime_.)
14546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    // Returns true on successful conversion.
14646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    bool UptimeDouble(double* result) const;
14746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
14846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    void RecordStats(const std::string& name) const;
14946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    void RecordStatsWithCallback(const std::string& name,
15046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                 const base::Closure& callback) const;
15146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
15246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)   private:
15346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    // Runs on BlockingPool
15446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    void RecordStatsImpl(const std::string& name) const;
15546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
15646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    std::string uptime_;
15746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    std::string disk_;
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void WriteTimes(const std::string base_name,
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         const std::string uma_name,
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         const std::string uma_prefix,
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         std::vector<TimeMarker> login_times);
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void AddMarker(std::vector<TimeMarker>* vector, TimeMarker marker);
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // Clear saved logout-started metric in Local State.
16746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // This method is called when logout-state was writen to file.
16846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  static void ClearLogoutStartedLastPreference();
16946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Used to hold the stats at main().
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Stats chrome_main_stats_;
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<Backend> backend_;
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Used to track notifications for login.
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::NotificationRegistrar registrar_;
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::AtomicSequenceNumber num_tabs_;
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool have_registered_;
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<TimeMarker> login_time_markers_;
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<TimeMarker> logout_time_markers_;
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::set<content::RenderWidgetHost*> render_widget_hosts_loading_;
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
183cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  bool login_done_;
184cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
185cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  bool restart_requested_;
186cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(BootTimesLoader);
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace chromeos
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // CHROME_BROWSER_CHROMEOS_BOOT_TIMES_LOADER_H_
193