1 // Copyright 2017 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_POLICY_OFF_HOURS_DEVICE_OFF_HOURS_CONTROLLER_H_
6 #define CHROME_BROWSER_CHROMEOS_POLICY_OFF_HOURS_DEVICE_OFF_HOURS_CONTROLLER_H_
7 
8 #include <memory>
9 #include <vector>
10 
11 #include "base/macros.h"
12 #include "base/memory/weak_ptr.h"
13 #include "base/observer_list.h"
14 #include "base/time/clock.h"
15 #include "base/time/time.h"
16 #include "base/util/timer/wall_clock_timer.h"
17 #include "chromeos/dbus/system_clock/system_clock_client.h"
18 #include "chromeos/policy/weekly_time/weekly_time_interval.h"
19 #include "components/policy/proto/chrome_device_policy.pb.h"
20 
21 namespace policy {
22 namespace off_hours {
23 
24 // The main class for handling "OffHours" policy turns "OffHours" mode on and
25 // off, handles server and client time, timezone.
26 //
27 // DeviceSettingsService is owner of this object. Use to get a reference:
28 // DeviceSettingsService::Get()->device_off_hours_controller()
29 //
30 // Device setting proto is changed in DeviceSettingsService and doesn't contain
31 // ignored device policies from DeviceOffHoursProto during "OffHours" mode. It
32 // is changed exactly in DeviceSettingsService because it's late to change
33 // policies in PrefValueMap and PolicyMap. The system will revert to the default
34 // behavior for the removed policies. And behavior of policies is handled during
35 // decoding process from proto to PolicyMap.
36 //
37 // "OffHours" mode is never on until device time is synchronized with
38 // network time because in this case device time could be incorrect.
39 class DeviceOffHoursController : public chromeos::SystemClockClient::Observer {
40  public:
41   // Observer interface.
42   class Observer {
43    public:
44     // Gets called when "OffHours" end time is changed.
OnOffHoursEndTimeChanged()45     virtual void OnOffHoursEndTimeChanged() {}
46 
47    protected:
~Observer()48     virtual ~Observer() {}
49   };
50 
51   // Creates a device off hours controller instance.
52   DeviceOffHoursController();
53   ~DeviceOffHoursController() override;
54 
55   void AddObserver(Observer* observer);
56   void RemoveObserver(Observer* observer);
57 
58   // Return current "OffHours" mode status.
is_off_hours_mode()59   bool is_off_hours_mode() const { return off_hours_mode_; }
60 
61   // Return true if the current user session is allowed only during the
62   // "OffHours" and will be signed out at the end of session. Always returns
63   // false outside of "OffHours".
64   bool IsCurrentSessionAllowedOnlyForOffHours() const;
65 
66   // Save actual "OffHours" intervals from |device_settings_proto| to
67   // |off_hours_intervals_| and call "UpdateOffhoursMode()".
68   void UpdateOffHoursPolicy(
69       const enterprise_management::ChromeDeviceSettingsProto&
70           device_settings_proto);
71 
72   // Return "OffHours" mode end time during "OffHours" mode is on. Return null
73   // when "OffHours" mode is off.
GetOffHoursEndTime()74   base::Time GetOffHoursEndTime() const { return off_hours_end_time_; }
75 
76   // chromeos::SystemClockClient::Observer:
77   void SystemClockUpdated() override;
78 
79   // |timer_clock| is not owned and its lifetime should cover lifetime of
80   // DeviceOffHoursContoller.
81   void SetClockForTesting(base::Clock* clock,
82                           const base::TickClock* timer_clock);
83 
84  private:
85   // Run OnOffHoursEndTimeChanged() for observers.
86   void NotifyOffHoursEndTimeChanged() const;
87 
88   // Called when "OffHours" mode is changed and ask DeviceSettingsService to
89   // update current proto.
90   void OffHoursModeIsChanged() const;
91 
92   // If device should be in "OffHours" mode based on the current time then apply
93   // current "OffHours" interval and turn "OffHours" mode on otherwise turn
94   // "OffHours" mode off and set timer to next update "OffHours" mode.
95   void UpdateOffHoursMode();
96 
97   // Turn on and off "OffHours" mode and call "OffHoursModeIsChanged()" if
98   // "OffHours" mode is changed.
99   void SetOffHoursMode(bool off_hours_enabled);
100 
101   // Set "OffHours" mode end time.
102   void SetOffHoursEndTime(base::Time off_hours_end_time);
103 
104   // Timer for update "OffHours" mode.
105   void StartOffHoursTimer(base::TimeDelta delay);
106   void StopOffHoursTimer();
107 
108   // Called once when the system clock service initially becomes available (or
109   // immediately if it's already available).
110   void SystemClockInitiallyAvailable(bool service_is_available);
111 
112   // Called when the system time synchronization status with network time is
113   // changed.
114   void NetworkSynchronizationUpdated(bool network_synchronized);
115 
116   base::ObserverList<Observer>::Unchecked observers_;
117 
118   // The main value of "OffHours" policy which indicates current "OffHours" mode
119   // state.
120   bool off_hours_mode_ = false;
121 
122   // "OffHours" mode end time. It is needed to show "OffHours" session limit
123   // notification. When "OffHours" mode is off the value is null.
124   base::Time off_hours_end_time_;
125 
126   // Timer for updating device settings at the begin of next “OffHours” interval
127   // or at the end of current "OffHours" interval.
128   std::unique_ptr<util::WallClockTimer> timer_;
129 
130   // Used for testing purposes, otherwise it's an instance of
131   // base::DefaultClock.
132   base::Clock* clock_;
133 
134   // Value is true if the system time is synchronized with network time, and
135   // false when synchronization failed. Value is not set until the response from
136   // the D-Bus call is not arrived.
137   base::Optional<bool> network_synchronized_;
138 
139   // Current "OffHours" time intervals.
140   std::vector<WeeklyTimeInterval> off_hours_intervals_;
141 
142   // Non-"OffHours" device settings proto.
143   // Needed to check policies outside of "OffHours" mode.
144   enterprise_management::ChromeDeviceSettingsProto device_settings_proto_;
145 
146   base::WeakPtrFactory<DeviceOffHoursController> weak_ptr_factory_{this};
147 
148   DISALLOW_COPY_AND_ASSIGN(DeviceOffHoursController);
149 };
150 
151 }  // namespace off_hours
152 }  // namespace policy
153 
154 #endif  // CHROME_BROWSER_CHROMEOS_POLICY_OFF_HOURS_DEVICE_OFF_HOURS_CONTROLLER_H_
155