1 // Copyright 2019 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_LOGIN_VERSION_UPDATER_VERSION_UPDATER_H_
6 #define CHROME_BROWSER_CHROMEOS_LOGIN_VERSION_UPDATER_VERSION_UPDATER_H_
7 
8 #include <memory>
9 #include <string>
10 
11 #include "base/macros.h"
12 #include "base/memory/weak_ptr.h"
13 #include "base/time/time.h"
14 #include "base/timer/timer.h"
15 #include "chrome/browser/chromeos/login/screens/network_error.h"
16 #include "chrome/browser/chromeos/login/version_updater/update_time_estimator.h"
17 #include "chromeos/dbus/update_engine_client.h"
18 #include "chromeos/network/portal_detector/network_portal_detector.h"
19 
20 namespace base {
21 class DefaultTickClock;
22 }
23 
24 namespace chromeos {
25 
26 // Tries to update system, interacting with UpdateEnglineClient and
27 // NetworkPortalDetector. Uses callbacks - methods of `delegate_`, which may
28 // interact with user, change UI etc.
29 class VersionUpdater : public UpdateEngineClient::Observer,
30                        public NetworkPortalDetector::Observer {
31  public:
32   enum class Result {
33     UPDATE_NOT_REQUIRED,
34     UPDATE_ERROR,
35     UPDATE_SKIPPED,
36   };
37 
38   enum class State {
39     STATE_IDLE = 0,
40     STATE_FIRST_PORTAL_CHECK,
41     STATE_REQUESTING_USER_PERMISSION,
42     STATE_UPDATE,
43     STATE_ERROR
44   };
45 
46   // Stores information about current downloading process, update progress and
47   // state.
48   struct UpdateInfo {
49     UpdateInfo();
50 
51     update_engine::StatusResult status;
52 
53     // Time left for an update to finish in seconds.
54     base::TimeDelta total_time_left;
55     // Progress of an update which is based on total time left expectation.
56     int better_update_progress = 0;
57 
58     // Estimated time left for only downloading stage, in seconds.
59     // TODO(crbug.com/1101317): Remove when better update is launched.
60     int estimated_time_left_in_secs = 0;
61     bool show_estimated_time_left = false;
62 
63     // True if VersionUpdater in such a state that progress is not available or
64     // applicable (e.g. checking for updates)
65     bool progress_unavailable = true;
66     base::string16 progress_message = base::string16();
67     // Percent of update progress, between 0 and 100.
68     int progress = 0;
69 
70     bool requires_permission_for_cellular = false;
71 
72     // Information about a pending update. Set if a user permission is required
73     // to proceed with the update. The values have to be passed to the update
74     // engine in SetUpdateOverCellularOneTimePermission method in order to
75     // enable update over cellular network.
76     int64_t update_size = 0;
77     std::string update_version = std::string();
78 
79     // True if in the process of checking for update.
80     bool is_checking_for_update = true;
81 
82     // Current state.
83     State state = State::STATE_IDLE;
84   };
85 
86   // Interface for callbacks that are called when corresponding events occur
87   // during update process.
88   class Delegate {
89    public:
90     // Called when update info changes
91     virtual void UpdateInfoChanged(
92         const VersionUpdater::UpdateInfo& update_info) = 0;
93     // Reports update results.
94     virtual void FinishExitUpdate(VersionUpdater::Result result) = 0;
95     // Timer notification handler.
96     virtual void OnWaitForRebootTimeElapsed() = 0;
97     // Called before update check starts.
98     virtual void PrepareForUpdateCheck() = 0;
99     virtual void UpdateErrorMessage(
100         const NetworkPortalDetector::CaptivePortalStatus status,
101         const NetworkError::ErrorState& error_state,
102         const std::string& network_name) = 0;
103     virtual void ShowErrorMessage() = 0;
104     virtual void DelayErrorMessage() = 0;
105   };
106 
107   // Callback type for `GetEOLInfo`
108   using EolInfoCallback =
109       base::OnceCallback<void(const UpdateEngineClient::EolInfo& eol_info)>;
110 
111   explicit VersionUpdater(VersionUpdater::Delegate* delegate);
112   ~VersionUpdater() override;
113 
114   // Resets `VersionUpdater` to initial state.
115   void Init();
116 
117   // Starts network check. If success, starts update check.
118   void StartNetworkCheck();
119   void StartUpdateCheck();
120 
121   void RefreshTimeLeftEstimation();
122 
123   void SetUpdateOverCellularOneTimePermission();
124   void RejectUpdateOverCellular();
125   void RebootAfterUpdate();
126   void StartExitUpdate(Result result);
127 
update_info()128   const UpdateInfo& update_info() { return update_info_; }
129 
130   // Has the device already reached its End Of Life (Auto Update Expiration) ?
131   void GetEolInfo(EolInfoCallback callback);
132 
set_tick_clock_for_testing(const base::TickClock * tick_clock)133   void set_tick_clock_for_testing(const base::TickClock* tick_clock) {
134     tick_clock_ = tick_clock;
135     time_estimator_.set_tick_clock_for_testing(tick_clock);
136   }
137 
set_wait_for_reboot_time_for_testing(base::TimeDelta wait_for_reboot_time)138   void set_wait_for_reboot_time_for_testing(
139       base::TimeDelta wait_for_reboot_time) {
140     wait_for_reboot_time_ = wait_for_reboot_time;
141   }
142 
143   base::OneShotTimer* GetRebootTimerForTesting();
144   void UpdateStatusChangedForTesting(const update_engine::StatusResult& status);
145 
146  private:
147   void RequestUpdateCheck();
148 
149   void OnGetEolInfo(EolInfoCallback cb, UpdateEngineClient::EolInfo info);
150 
151   // UpdateEngineClient::Observer implementation:
152   void UpdateStatusChanged(const update_engine::StatusResult& status) override;
153 
154   // NetworkPortalDetector::Observer implementation:
155   void OnPortalDetectionCompleted(
156       const NetworkState* network,
157       const NetworkPortalDetector::CaptivePortalStatus status) override;
158 
159   void OnWaitForRebootTimeElapsed();
160 
161   void UpdateErrorMessage(
162       const NetworkState* network,
163       const NetworkPortalDetector::CaptivePortalStatus status);
164 
165   // Callback to UpdateEngineClient::SetUpdateOverCellularOneTimePermission
166   // called in response to user confirming that the OS update can proceed
167   // despite being over cellular charges.
168   // `success`: whether the update engine accepted the user permission.
169   void OnSetUpdateOverCellularOneTimePermission(bool success);
170 
171   // Callback for UpdateEngineClient::RequestUpdateCheck() called from
172   // StartUpdateCheck().
173   void OnUpdateCheckStarted(UpdateEngineClient::UpdateCheckResult result);
174 
175   // Pointer to delegate that owns this VersionUpdater instance.
176   Delegate* delegate_;
177 
178   std::unique_ptr<base::RepeatingTimer> refresh_timer_;
179 
180   // Timer for the interval to wait for the reboot.
181   // If reboot didn't happen - ask user to reboot manually.
182   base::OneShotTimer reboot_timer_;
183   // Time in seconds after which we decide that the device has not rebooted
184   // automatically. If reboot didn't happen during this interval, ask user to
185   // reboot device manually.
186   base::TimeDelta wait_for_reboot_time_;
187 
188   // True if there was no notification from NetworkPortalDetector
189   // about state for the default network.
190   bool is_first_detection_notification_ = true;
191 
192   // Ignore fist IDLE status that is sent before VersionUpdater initiated check.
193   bool ignore_idle_status_ = true;
194 
195   // Stores information about current downloading process, update progress and
196   // state. It is sent to Delegate on each UpdateInfoChanged call, and also can
197   // be obtained with corresponding getter.
198   UpdateInfo update_info_;
199 
200   UpdateTimeEstimator time_estimator_;
201 
202   const base::TickClock* tick_clock_;
203 
204   base::WeakPtrFactory<VersionUpdater> weak_ptr_factory_{this};
205 
206   DISALLOW_COPY_AND_ASSIGN(VersionUpdater);
207 };
208 
209 }  // namespace chromeos
210 
211 #endif  // CHROME_BROWSER_CHROMEOS_LOGIN_VERSION_UPDATER_VERSION_UPDATER_H_
212