1// Copyright (c) 2013 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_SYSTEM_AUTOMATIC_REBOOT_MANAGER_H_
6#define CHROME_BROWSER_CHROMEOS_SYSTEM_AUTOMATIC_REBOOT_MANAGER_H_
7
8#include "base/basictypes.h"
9#include "base/compiler_specific.h"
10#include "base/memory/scoped_ptr.h"
11#include "base/memory/weak_ptr.h"
12#include "base/observer_list.h"
13#include "base/prefs/pref_change_registrar.h"
14#include "base/time/time.h"
15#include "base/timer/timer.h"
16#include "chromeos/dbus/power_manager_client.h"
17#include "chromeos/dbus/update_engine_client.h"
18#include "content/public/browser/notification_observer.h"
19#include "content/public/browser/notification_registrar.h"
20#include "ui/wm/core/user_activity_observer.h"
21
22class PrefRegistrySimple;
23
24namespace base {
25class TickClock;
26}
27
28namespace chromeos {
29namespace system {
30
31class AutomaticRebootManagerObserver;
32
33// Schedules and executes automatic reboots.
34//
35// Automatic reboots may be scheduled for any number of reasons. Currently, the
36// following are implemented:
37// * When Chrome OS has applied a system update, a reboot may become necessary
38//   to complete the update process. If the policy to automatically reboot after
39//   an update is enabled, a reboot is scheduled at that point.
40// * If an uptime limit is set through policy, a reboot is scheduled when the
41//   device's uptime reaches the limit. Time spent sleeping counts as uptime as
42//   well.
43//
44// When the time of the earliest scheduled reboot is reached, the reboot is
45// requested. The reboot is performed immediately unless one of the following
46// reasons inhibits it:
47// * If the login screen is being shown: Reboots are inhibited while the user is
48//   interacting with the screen (determined by checking whether there has been
49//   any user activity in the past 60 seconds).
50// * If a session is in progress: Reboots are inhibited until the session ends,
51//   the browser is restarted or the device is suspended.
52//
53// If reboots are inhibited, a 24 hour grace period is started. The reboot
54// request is carried out the moment none of the inhibiting criteria apply
55// anymore (e.g. the user becomes idle on the login screen, the user logs exits
56// a session, the user suspends the device). If reboots remain inhibited for the
57// entire grace period, a reboot is unconditionally performed at its end.
58//
59// Note: Currently, automatic reboots are only enabled while the login screen is
60// being shown or a kiosk app session is in progress. This will change in the
61// future and the policy will always apply, regardless of whether a session of
62// any particular type is in progress or not. http://crbug.com/244972
63//
64// Reboots may be scheduled and canceled at any time. This causes the time at
65// which a reboot should be requested and the grace period that follows it to
66// be recalculated.
67//
68// Reboots are scheduled in terms of device uptime. The current uptime is read
69// from /proc/uptime. The time at which a reboot became necessary to finish
70// applying an update is stored in /var/run/chrome/update_reboot_needed_uptime,
71// making it persist across browser restarts and crashes. Placing the file under
72// /var/run ensures that it gets cleared automatically on every boot.
73class AutomaticRebootManager : public PowerManagerClient::Observer,
74                               public UpdateEngineClient::Observer,
75                               public wm::UserActivityObserver,
76                               public content::NotificationObserver {
77 public:
78  // The current uptime and the uptime at which an update was applied and a
79  // reboot became necessary (if any). Used to pass this information from the
80  // blocking thread pool to the UI thread.
81  struct SystemEventTimes {
82    SystemEventTimes();
83    SystemEventTimes(const base::TimeDelta& uptime,
84                     const base::TimeDelta& update_reboot_needed_uptime);
85
86    bool has_boot_time;
87    base::TimeTicks boot_time;
88
89    bool has_update_reboot_needed_time;
90    base::TimeTicks update_reboot_needed_time;
91  };
92
93  explicit AutomaticRebootManager(scoped_ptr<base::TickClock> clock);
94  virtual ~AutomaticRebootManager();
95
96  void AddObserver(AutomaticRebootManagerObserver* observer);
97  void RemoveObserver(AutomaticRebootManagerObserver* observer);
98
99  // PowerManagerClient::Observer:
100  virtual void SuspendDone(const base::TimeDelta& sleep_duration) OVERRIDE;
101
102  // UpdateEngineClient::Observer:
103  virtual void UpdateStatusChanged(
104      const UpdateEngineClient::Status& status) OVERRIDE;
105
106  // wm::UserActivityObserver:
107  virtual void OnUserActivity(const ui::Event* event) OVERRIDE;
108
109  // content::NotificationObserver:
110  virtual void Observe(int type,
111                       const content::NotificationSource& source,
112                       const content::NotificationDetails& details) OVERRIDE;
113
114  static void RegisterPrefs(PrefRegistrySimple* registry);
115
116 private:
117  friend class AutomaticRebootManagerBasicTest;
118
119  // Finishes initialization. Called after the |system_event_times| have been
120  // loaded in the blocking thread pool.
121  void Init(const SystemEventTimes& system_event_times);
122
123  // Reschedules the reboot request, start and end of the grace period. Reboots
124  // immediately if the end of the grace period has already passed.
125  void Reschedule();
126
127  // Requests a reboot.
128  void RequestReboot();
129
130  // Called whenever the status of the criteria inhibiting reboots may have
131  // changed. Reboots immediately if a reboot has actually been requested and
132  // none of the criteria inhibiting it apply anymore. Otherwise, does nothing.
133  // If |ignore_session|, a session in progress does not inhibit reboots.
134  void MaybeReboot(bool ignore_session);
135
136  // Reboots immediately.
137  void Reboot();
138
139  // A clock that can be mocked in tests to fast-forward time.
140  scoped_ptr<base::TickClock> clock_;
141
142  PrefChangeRegistrar local_state_registrar_;
143
144  content::NotificationRegistrar notification_registrar_;
145
146  // Fires when the user has been idle on the login screen for a set amount of
147  // time.
148  scoped_ptr<base::OneShotTimer<AutomaticRebootManager> >
149      login_screen_idle_timer_;
150
151  // The time at which the device was booted, in |clock_| ticks.
152  bool have_boot_time_;
153  base::TimeTicks boot_time_;
154
155  // The time at which an update was applied and a reboot became necessary to
156  // complete the update process, in |clock_| ticks.
157  bool have_update_reboot_needed_time_;
158  base::TimeTicks update_reboot_needed_time_;
159
160  // Whether a reboot has been requested.
161  bool reboot_requested_;
162
163  // Timers that start and end the grace period.
164  scoped_ptr<base::OneShotTimer<AutomaticRebootManager> > grace_start_timer_;
165  scoped_ptr<base::OneShotTimer<AutomaticRebootManager> > grace_end_timer_;
166
167  ObserverList<AutomaticRebootManagerObserver, true> observers_;
168
169  base::WeakPtrFactory<AutomaticRebootManager> weak_ptr_factory_;
170
171  DISALLOW_COPY_AND_ASSIGN(AutomaticRebootManager);
172};
173
174}  // namespace system
175}  // namespace chromeos
176
177#endif  // CHROME_BROWSER_CHROMEOS_SYSTEM_AUTOMATIC_REBOOT_MANAGER_H_
178