File: minimum_version_policy_handler.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (328 lines) | stat: -rw-r--r-- 12,489 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_ASH_POLICY_HANDLERS_MINIMUM_VERSION_POLICY_HANDLER_H_
#define CHROME_BROWSER_ASH_POLICY_HANDLERS_MINIMUM_VERSION_POLICY_HANDLER_H_

#include <memory>

#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/scoped_observation.h"
#include "base/time/time.h"
#include "base/timer/wall_clock_timer.h"
#include "base/version.h"
#include "chrome/browser/upgrade_detector/build_state_observer.h"
#include "chromeos/ash/components/dbus/update_engine/update_engine_client.h"
#include "chromeos/ash/components/network/network_state_handler_observer.h"
#include "chromeos/ash/components/settings/cros_settings.h"

class PrefRegistrySimple;

namespace ash {
class NetworkStateHandler;
class UpdateRequiredNotification;
}  // namespace ash

namespace base {
class Clock;
class Time;
}  // namespace base

namespace policy {

// This class observes the device setting |kDeviceMinimumVersion|, and
// checks if respective requirement is met. If an update is not required, all
// running timers are reset. If an update is required, it calculates the
// deadline using the warning period in the policy and restarts the timer. It
// also calls UpdateRequiredNotification to show in-session notifications if an
// update is required but it cannot be downloaded due to network limitations or
// Auto Update Expiration.
class MinimumVersionPolicyHandler : public BuildStateObserver,
                                    public ash::NetworkStateHandlerObserver,
                                    public ash::UpdateEngineClient::Observer {
 public:
  static const char kRequirements[];
  static const char kChromeOsVersion[];
  static const char kWarningPeriod[];
  static const char kEolWarningPeriod[];
  static const char kUnmanagedUserRestricted[];

  class Observer {
   public:
    virtual void OnMinimumVersionStateChanged() = 0;
    virtual ~Observer() = default;
  };

  // Delegate of MinimumVersionPolicyHandler to handle the external
  // dependencies.
  class Delegate {
   public:
    virtual ~Delegate() = default;

    // Checks if the user is logged in as any kiosk app or this is an
    // auto-launch kiosk device.
    virtual bool IsKioskMode() const = 0;

    // Checks if the device is enterprise managed.
    virtual bool IsDeviceEnterpriseManaged() const = 0;

    // Checks if a user is logged in.
    virtual bool IsUserLoggedIn() const = 0;

    // Checks if the user logged in is managed and not a child user.
    virtual bool IsUserEnterpriseManaged() const = 0;

    // Checks if we are currently on the login screen.
    virtual bool IsLoginSessionState() const = 0;

    // Checks if login is in progress before starting user session.
    virtual bool IsLoginInProgress() const = 0;

    // Shows the update required screen.
    virtual void ShowUpdateRequiredScreen() = 0;

    // Terminates the current session and restarts Chrome to show the login
    // screen.
    virtual void RestartToLoginScreen() = 0;

    // Hides update required screen and shows the login screen.
    virtual void HideUpdateRequiredScreenIfShown() = 0;

    virtual base::Version GetCurrentVersion() const = 0;
  };

  class MinimumVersionRequirement {
   public:
    MinimumVersionRequirement(const base::Version version,
                              const base::TimeDelta warning,
                              const base::TimeDelta eol_warning);

    MinimumVersionRequirement(const MinimumVersionRequirement&) = delete;

    // Method used to create an instance of MinimumVersionRequirement from
    // dictionary if it contains valid version string.
    static std::unique_ptr<MinimumVersionRequirement> CreateInstanceIfValid(
        const base::Value::Dict& dict);

    // This is used to compare two MinimumVersionRequirement objects
    // and returns 1 if the first object has version or warning time
    // or eol warning time greater than that the second, -1 if the
    // its version or warning time or eol warning time is less than the second,
    // else 0.
    int Compare(const MinimumVersionRequirement* other) const;

    base::Version version() const { return minimum_version_; }
    base::TimeDelta warning() const { return warning_time_; }
    base::TimeDelta eol_warning() const { return eol_warning_time_; }

   private:
    base::Version minimum_version_;
    base::TimeDelta warning_time_;
    base::TimeDelta eol_warning_time_;
  };

  enum class NetworkStatus { kAllowed, kMetered, kOffline };

  enum class NotificationType {
    kMeteredConnection,
    kNoConnection,
    kEolReached
  };

  explicit MinimumVersionPolicyHandler(Delegate* delegate,
                                       ash::CrosSettings* cros_settings);

  MinimumVersionPolicyHandler(const MinimumVersionPolicyHandler&) = delete;
  MinimumVersionPolicyHandler& operator=(const MinimumVersionPolicyHandler&) =
      delete;

  ~MinimumVersionPolicyHandler() override;

  // BuildStateObserver:
  void OnUpdate(const BuildState* build_state) override;

  // NetworkStateHandlerObserver:
  void DefaultNetworkChanged(const ash::NetworkState* network) override;
  void OnShuttingDown() override;

  // UpdateEngineClient::Observer:
  void UpdateStatusChanged(const update_engine::StatusResult& status) override;

  void AddObserver(Observer* observer);
  void RemoveObserver(Observer* observer);
  bool RequirementsAreSatisfied() const { return GetState() == nullptr; }

  const MinimumVersionRequirement* GetState() const { return state_.get(); }

  bool DeadlineReached() { return deadline_reached_; }

  static void RegisterPrefs(PrefRegistrySimple* registry);

  // Show notification on login if the user is managed or
  // |unmanaged_user_restricted_| is set to true if it is the last day to
  // deadline.
  void MaybeShowNotificationOnLogin();

  // Whether banner to return back the device should be visible in Settings. It
  // is true when an update is required on a device that has reached End Of Life
  // (Auto Update Expiration) and the currently signed in user is enterprise
  // managed or an unmanaged user restricted by DeviceMinimumVersion policy.
  bool ShouldShowUpdateRequiredEolBanner() const;

  // Returns the number of days to deadline if update is required and deadline
  // has not been reached. Returns null if update is not required.
  std::optional<int> GetTimeRemainingInDays();

  // Callback used in tests and invoked after end-of-life status has been
  // fetched from the update_engine.
  void set_fetch_eol_callback_for_testing(base::OnceClosure callback) {
    fetch_eol_callback_ = std::move(callback);
  }

  base::Time update_required_deadline_for_testing() const {
    return update_required_deadline_;
  }

  bool IsDeadlineTimerRunningForTesting() const;

 private:
  // Returns |true| if the current version satisfies the given requirement.
  bool CurrentVersionSatisfies(
      const MinimumVersionRequirement& requirement) const;

  // Whether the current user should receive update required notifications and
  // force signed out on reaching the deadline. Retuns true if the user is
  // enterprise managed or |unmanaged_user_restricted_| is true.
  bool IsPolicyRestrictionAppliedForUser() const;

  void OnPolicyChanged();
  bool IsPolicyApplicable();
  void Reset();

  // Handles post update completed actions like reset timers, hide update
  // required notification and stop observing build state.
  void ResetOnUpdateCompleted();

  // Handles the state when update is required as per the policy. If on the
  // login screen, update required screen is shown, else the user is logged out
  // if the device is not updated within the given |warning_time|. The
  // |warning_time| is supplied by the policy.
  void HandleUpdateRequired(base::TimeDelta warning_time);

  void HandleUpdateNotRequired();

  // Invokes update_engine_client to fetch the end-of-life status of the device.
  void FetchEolInfo();

  // Callback after fetching end-of-life info from the update_engine_client.
  void OnFetchEolInfo(ash::UpdateEngineClient::EolInfo info);

  // Called when the warning time to apply updates has expired. If the user on
  // the login screen, the update required screen is shown else the current user
  // session is terminated to bring the user back to the login screen.
  void OnDeadlineReached();

  // Starts the timer to expire when |deadline| is reached.
  void StartDeadlineTimer(base::Time deadline);

  // Starts observing the BuildState for any updates in Chrome OS and resets the
  // state if new version satisfies the minimum version requirement.
  void StartObservingUpdate();

  // Shows notification for a managed logged in user if update is required and
  // the device can not be updated due to end-of-life or network limitations.
  void MaybeShowNotification(base::TimeDelta warning);

  // Shows notification if required and starts a timer to expire when the next
  // notification is to be shown.
  void ShowAndScheduleNotification(base::Time deadline);

  void HideNotification() const;

  void StopObservingNetwork();

  // Start updating over metered network as user has given consent through
  // notification click.
  void UpdateOverMeteredPermssionGranted();

  // Tells whether starting an update check succeeded or not.
  void OnUpdateCheckStarted(ash::UpdateEngineClient::UpdateCheckResult result);

  // Callback from UpdateEngineClient::SetUpdateOverCellularOneTimePermission().
  void OnSetUpdateOverCellularOneTimePermission(bool success);

  // Updates pref |kUpdateRequiredWarningPeriod| in local state to
  // |warning_time|. If |kUpdateRequiredTimerStartTime| is not null, it means
  // update is already required and hence, the timer start time should not be
  // updated.
  void UpdateLocalState(base::TimeDelta warning_time);

  // Resets the local state prefs to default values.
  void ResetLocalState();

  // This delegate instance is owned by the owner of
  // MinimumVersionPolicyHandler. The owner is responsible to make sure that the
  // delegate lives throughout the life of the policy handler.
  raw_ptr<Delegate> delegate_;

  // This represents the current minimum version requirement.
  // It is chosen as one of the configurations specified in the policy. It is
  // set to nullptr if the current version is higher than the minimum required
  // version in all the configurations.
  std::unique_ptr<MinimumVersionRequirement> state_;

  // If this flag is true, unmanaged user sessions receive update required
  // notifications and are force logged out when deadline is reached.
  bool unmanaged_user_restricted_ = false;

  bool eol_reached_ = false;

  // If this flag is true, user should restricted to use the session by logging
  // out and/or showing update required screen.
  bool deadline_reached_ = false;

  // Time when the policy is applied and with respect to which the deadline to
  // update the device is calculated.
  base::Time update_required_time_;

  // Deadline for updating the device post which the user is restricted from
  // using the session by force log out if a session is active and then blocking
  // sign in at the login screen.
  base::Time update_required_deadline_;

  // Fires when the deadline to update the device has reached or passed.
  base::WallClockTimer update_required_deadline_timer_;

  // Fires when next update required notification is to be shown.
  base::WallClockTimer notification_timer_;

  // Non-owning reference to CrosSettings. This class have shorter lifetime than
  // CrosSettings.
  raw_ptr<ash::CrosSettings> cros_settings_;

  const raw_ptr<base::Clock> clock_;

  base::OnceClosure fetch_eol_callback_;

  base::CallbackListSubscription policy_subscription_;

  // Handles showing in-session update required notifications on the basis of
  // current network and time to reach the deadline.
  std::unique_ptr<ash::UpdateRequiredNotification> notification_handler_;

  base::ScopedObservation<ash::NetworkStateHandler,
                          ash::NetworkStateHandlerObserver>
      network_state_handler_observer_{this};

  // List of registered observers.
  base::ObserverList<Observer>::Unchecked observers_;

  base::WeakPtrFactory<MinimumVersionPolicyHandler> weak_factory_{this};
};

}  // namespace policy

#endif  // CHROME_BROWSER_ASH_POLICY_HANDLERS_MINIMUM_VERSION_POLICY_HANDLER_H_