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