| Alex Deymo | aea4c1c | 2015-08-19 20:24:43 -0700 | [diff] [blame] | 1 | // | 
|  | 2 | // Copyright (C) 2014 The Android Open Source Project | 
|  | 3 | // | 
|  | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | 5 | // you may not use this file except in compliance with the License. | 
|  | 6 | // You may obtain a copy of the License at | 
|  | 7 | // | 
|  | 8 | //      http://www.apache.org/licenses/LICENSE-2.0 | 
|  | 9 | // | 
|  | 10 | // Unless required by applicable law or agreed to in writing, software | 
|  | 11 | // distributed under the License is distributed on an "AS IS" BASIS, | 
|  | 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | 13 | // See the License for the specific language governing permissions and | 
|  | 14 | // limitations under the License. | 
|  | 15 | // | 
| Gilad Arnold | ae47a9a | 2014-03-26 12:16:47 -0700 | [diff] [blame] | 16 |  | 
| Alex Deymo | 63784a5 | 2014-05-28 10:46:14 -0700 | [diff] [blame] | 17 | #include "update_engine/update_manager/real_updater_provider.h" | 
| Gilad Arnold | ae47a9a | 2014-03-26 12:16:47 -0700 | [diff] [blame] | 18 |  | 
|  | 19 | #include <inttypes.h> | 
|  | 20 |  | 
| Amin Hassani | 03277de | 2020-07-28 12:32:49 -0700 | [diff] [blame] | 21 | #include <algorithm> | 
| Gilad Arnold | ae47a9a | 2014-03-26 12:16:47 -0700 | [diff] [blame] | 22 | #include <string> | 
|  | 23 |  | 
| Gilad Arnold | 44dc3bf | 2014-07-18 23:39:38 -0700 | [diff] [blame] | 24 | #include <base/bind.h> | 
| Gilad Arnold | ae47a9a | 2014-03-26 12:16:47 -0700 | [diff] [blame] | 25 | #include <base/strings/stringprintf.h> | 
| Alex Deymo | c7ab616 | 2014-04-25 18:32:50 -0700 | [diff] [blame] | 26 | #include <base/time/time.h> | 
| Alex Deymo | d6deb1d | 2015-08-28 15:54:37 -0700 | [diff] [blame] | 27 | #include <update_engine/dbus-constants.h> | 
| Gilad Arnold | ae47a9a | 2014-03-26 12:16:47 -0700 | [diff] [blame] | 28 |  | 
| Aaron Wood | 7f92e2b | 2017-08-28 14:51:21 -0700 | [diff] [blame] | 29 | #include "update_engine/client_library/include/update_engine/update_status.h" | 
| Alex Deymo | 39910dc | 2015-11-09 17:04:30 -0800 | [diff] [blame] | 30 | #include "update_engine/common/prefs.h" | 
| Amin Hassani | 538bd59 | 2020-11-04 20:46:08 -0800 | [diff] [blame] | 31 | #include "update_engine/common/system_state.h" | 
| Amin Hassani | ec7bc11 | 2020-10-29 16:47:58 -0700 | [diff] [blame] | 32 | #include "update_engine/cros/omaha_request_params.h" | 
|  | 33 | #include "update_engine/cros/update_attempter.h" | 
| Aaron Wood | 7f92e2b | 2017-08-28 14:51:21 -0700 | [diff] [blame] | 34 | #include "update_engine/update_status_utils.h" | 
| Gilad Arnold | ae47a9a | 2014-03-26 12:16:47 -0700 | [diff] [blame] | 35 |  | 
|  | 36 | using base::StringPrintf; | 
|  | 37 | using base::Time; | 
|  | 38 | using base::TimeDelta; | 
|  | 39 | using chromeos_update_engine::OmahaRequestParams; | 
|  | 40 | using chromeos_update_engine::SystemState; | 
|  | 41 | using std::string; | 
| Aaron Wood | bf5a252 | 2017-10-04 10:58:36 -0700 | [diff] [blame] | 42 | using update_engine::UpdateAttemptFlags; | 
| Aaron Wood | 7f92e2b | 2017-08-28 14:51:21 -0700 | [diff] [blame] | 43 | using update_engine::UpdateEngineStatus; | 
| Gilad Arnold | ae47a9a | 2014-03-26 12:16:47 -0700 | [diff] [blame] | 44 |  | 
| Alex Deymo | 63784a5 | 2014-05-28 10:46:14 -0700 | [diff] [blame] | 45 | namespace chromeos_update_manager { | 
| Gilad Arnold | ae47a9a | 2014-03-26 12:16:47 -0700 | [diff] [blame] | 46 |  | 
|  | 47 | // A templated base class for all update related variables. Provides uniform | 
|  | 48 | // construction and a system state handle. | 
| Amin Hassani | 4b71743 | 2019-01-14 16:24:20 -0800 | [diff] [blame] | 49 | template <typename T> | 
| Gilad Arnold | ae47a9a | 2014-03-26 12:16:47 -0700 | [diff] [blame] | 50 | class UpdaterVariableBase : public Variable<T> { | 
|  | 51 | public: | 
| Amin Hassani | 538bd59 | 2020-11-04 20:46:08 -0800 | [diff] [blame] | 52 | UpdaterVariableBase(const string& name, VariableMode mode) | 
|  | 53 | : Variable<T>(name, mode) {} | 
| Gilad Arnold | ae47a9a | 2014-03-26 12:16:47 -0700 | [diff] [blame] | 54 | }; | 
|  | 55 |  | 
|  | 56 | // Helper class for issuing a GetStatus() to the UpdateAttempter. | 
|  | 57 | class GetStatusHelper { | 
|  | 58 | public: | 
| Amin Hassani | 538bd59 | 2020-11-04 20:46:08 -0800 | [diff] [blame] | 59 | explicit GetStatusHelper(string* errmsg) { | 
|  | 60 | is_success_ = SystemState::Get()->update_attempter()->GetStatus( | 
|  | 61 | &update_engine_status_); | 
| Aaron Wood | 7f92e2b | 2017-08-28 14:51:21 -0700 | [diff] [blame] | 62 | if (!is_success_ && errmsg) { | 
| Gilad Arnold | ae47a9a | 2014-03-26 12:16:47 -0700 | [diff] [blame] | 63 | *errmsg = "Failed to get a status update from the update engine"; | 
| Aaron Wood | 7f92e2b | 2017-08-28 14:51:21 -0700 | [diff] [blame] | 64 | } | 
| Gilad Arnold | ae47a9a | 2014-03-26 12:16:47 -0700 | [diff] [blame] | 65 | } | 
|  | 66 |  | 
|  | 67 | inline bool is_success() { return is_success_; } | 
| Aaron Wood | 7f92e2b | 2017-08-28 14:51:21 -0700 | [diff] [blame] | 68 | inline int64_t last_checked_time() { | 
| Aaron Wood | 795c5b4 | 2017-12-05 16:06:13 -0800 | [diff] [blame] | 69 | return update_engine_status_.last_checked_time; | 
| Aaron Wood | 7f92e2b | 2017-08-28 14:51:21 -0700 | [diff] [blame] | 70 | } | 
|  | 71 | inline double progress() { return update_engine_status_.progress; } | 
|  | 72 | inline const string update_status() { | 
|  | 73 | return chromeos_update_engine::UpdateStatusToString( | 
|  | 74 | update_engine_status_.status); | 
|  | 75 | } | 
|  | 76 | inline const string& new_version() { | 
|  | 77 | return update_engine_status_.new_version; | 
|  | 78 | } | 
|  | 79 | inline uint64_t payload_size() { | 
|  | 80 | return update_engine_status_.new_size_bytes; | 
|  | 81 | } | 
| Gilad Arnold | ae47a9a | 2014-03-26 12:16:47 -0700 | [diff] [blame] | 82 |  | 
|  | 83 | private: | 
|  | 84 | bool is_success_; | 
| Aaron Wood | 7f92e2b | 2017-08-28 14:51:21 -0700 | [diff] [blame] | 85 | UpdateEngineStatus update_engine_status_; | 
| Gilad Arnold | ae47a9a | 2014-03-26 12:16:47 -0700 | [diff] [blame] | 86 | }; | 
|  | 87 |  | 
|  | 88 | // A variable reporting the time when a last update check was issued. | 
|  | 89 | class LastCheckedTimeVariable : public UpdaterVariableBase<Time> { | 
|  | 90 | public: | 
| Amin Hassani | 538bd59 | 2020-11-04 20:46:08 -0800 | [diff] [blame] | 91 | explicit LastCheckedTimeVariable(const string& name) | 
|  | 92 | : UpdaterVariableBase<Time>(name, kVariableModePoll) {} | 
| Gilad Arnold | ae47a9a | 2014-03-26 12:16:47 -0700 | [diff] [blame] | 93 |  | 
|  | 94 | private: | 
| Alex Vakulenko | 157fe30 | 2014-08-11 15:59:58 -0700 | [diff] [blame] | 95 | const Time* GetValue(TimeDelta /* timeout */, string* errmsg) override { | 
| Amin Hassani | 538bd59 | 2020-11-04 20:46:08 -0800 | [diff] [blame] | 96 | GetStatusHelper raw(errmsg); | 
| Gilad Arnold | ae47a9a | 2014-03-26 12:16:47 -0700 | [diff] [blame] | 97 | if (!raw.is_success()) | 
| Alex Vakulenko | 88b591f | 2014-08-28 16:48:57 -0700 | [diff] [blame] | 98 | return nullptr; | 
| Gilad Arnold | ae47a9a | 2014-03-26 12:16:47 -0700 | [diff] [blame] | 99 |  | 
|  | 100 | return new Time(Time::FromTimeT(raw.last_checked_time())); | 
|  | 101 | } | 
|  | 102 |  | 
|  | 103 | DISALLOW_COPY_AND_ASSIGN(LastCheckedTimeVariable); | 
|  | 104 | }; | 
|  | 105 |  | 
|  | 106 | // A variable reporting the update (download) progress as a decimal fraction | 
|  | 107 | // between 0.0 and 1.0. | 
|  | 108 | class ProgressVariable : public UpdaterVariableBase<double> { | 
|  | 109 | public: | 
| Amin Hassani | 538bd59 | 2020-11-04 20:46:08 -0800 | [diff] [blame] | 110 | explicit ProgressVariable(const string& name) | 
|  | 111 | : UpdaterVariableBase<double>(name, kVariableModePoll) {} | 
| Gilad Arnold | ae47a9a | 2014-03-26 12:16:47 -0700 | [diff] [blame] | 112 |  | 
|  | 113 | private: | 
| Alex Vakulenko | 157fe30 | 2014-08-11 15:59:58 -0700 | [diff] [blame] | 114 | const double* GetValue(TimeDelta /* timeout */, string* errmsg) override { | 
| Amin Hassani | 538bd59 | 2020-11-04 20:46:08 -0800 | [diff] [blame] | 115 | GetStatusHelper raw(errmsg); | 
| Gilad Arnold | ae47a9a | 2014-03-26 12:16:47 -0700 | [diff] [blame] | 116 | if (!raw.is_success()) | 
| Alex Vakulenko | 88b591f | 2014-08-28 16:48:57 -0700 | [diff] [blame] | 117 | return nullptr; | 
| Gilad Arnold | ae47a9a | 2014-03-26 12:16:47 -0700 | [diff] [blame] | 118 |  | 
|  | 119 | if (raw.progress() < 0.0 || raw.progress() > 1.0) { | 
|  | 120 | if (errmsg) { | 
| Amin Hassani | 4b71743 | 2019-01-14 16:24:20 -0800 | [diff] [blame] | 121 | *errmsg = | 
|  | 122 | StringPrintf("Invalid progress value received: %f", raw.progress()); | 
| Gilad Arnold | ae47a9a | 2014-03-26 12:16:47 -0700 | [diff] [blame] | 123 | } | 
| Alex Vakulenko | 88b591f | 2014-08-28 16:48:57 -0700 | [diff] [blame] | 124 | return nullptr; | 
| Gilad Arnold | ae47a9a | 2014-03-26 12:16:47 -0700 | [diff] [blame] | 125 | } | 
|  | 126 |  | 
|  | 127 | return new double(raw.progress()); | 
|  | 128 | } | 
|  | 129 |  | 
|  | 130 | DISALLOW_COPY_AND_ASSIGN(ProgressVariable); | 
|  | 131 | }; | 
|  | 132 |  | 
|  | 133 | // A variable reporting the stage in which the update process is. | 
|  | 134 | class StageVariable : public UpdaterVariableBase<Stage> { | 
|  | 135 | public: | 
| Amin Hassani | 538bd59 | 2020-11-04 20:46:08 -0800 | [diff] [blame] | 136 | explicit StageVariable(const string& name) | 
|  | 137 | : UpdaterVariableBase<Stage>(name, kVariableModePoll) {} | 
| Gilad Arnold | ae47a9a | 2014-03-26 12:16:47 -0700 | [diff] [blame] | 138 |  | 
|  | 139 | private: | 
|  | 140 | struct CurrOpStrToStage { | 
|  | 141 | const char* str; | 
|  | 142 | Stage stage; | 
|  | 143 | }; | 
|  | 144 | static const CurrOpStrToStage curr_op_str_to_stage[]; | 
|  | 145 |  | 
|  | 146 | // Note: the method is defined outside the class so arraysize can work. | 
| Alex Vakulenko | 157fe30 | 2014-08-11 15:59:58 -0700 | [diff] [blame] | 147 | const Stage* GetValue(TimeDelta /* timeout */, string* errmsg) override; | 
| Gilad Arnold | ae47a9a | 2014-03-26 12:16:47 -0700 | [diff] [blame] | 148 |  | 
|  | 149 | DISALLOW_COPY_AND_ASSIGN(StageVariable); | 
|  | 150 | }; | 
|  | 151 |  | 
|  | 152 | const StageVariable::CurrOpStrToStage StageVariable::curr_op_str_to_stage[] = { | 
| Amin Hassani | 4b71743 | 2019-01-14 16:24:20 -0800 | [diff] [blame] | 153 | {update_engine::kUpdateStatusIdle, Stage::kIdle}, | 
|  | 154 | {update_engine::kUpdateStatusCheckingForUpdate, Stage::kCheckingForUpdate}, | 
|  | 155 | {update_engine::kUpdateStatusUpdateAvailable, Stage::kUpdateAvailable}, | 
|  | 156 | {update_engine::kUpdateStatusDownloading, Stage::kDownloading}, | 
|  | 157 | {update_engine::kUpdateStatusVerifying, Stage::kVerifying}, | 
|  | 158 | {update_engine::kUpdateStatusFinalizing, Stage::kFinalizing}, | 
|  | 159 | {update_engine::kUpdateStatusUpdatedNeedReboot, Stage::kUpdatedNeedReboot}, | 
|  | 160 | {update_engine::kUpdateStatusReportingErrorEvent, | 
|  | 161 | Stage::kReportingErrorEvent}, | 
|  | 162 | {update_engine::kUpdateStatusAttemptingRollback, | 
|  | 163 | Stage::kAttemptingRollback}, | 
| Amin Hassani | 70a90f5 | 2020-09-15 15:30:09 -0700 | [diff] [blame] | 164 | {update_engine::kUpdateStatusCleanupPreviousUpdate, | 
|  | 165 | Stage::kCleanupPreviousUpdate}, | 
| Gilad Arnold | ae47a9a | 2014-03-26 12:16:47 -0700 | [diff] [blame] | 166 | }; | 
|  | 167 |  | 
| Amin Hassani | 4b71743 | 2019-01-14 16:24:20 -0800 | [diff] [blame] | 168 | const Stage* StageVariable::GetValue(TimeDelta /* timeout */, string* errmsg) { | 
| Amin Hassani | 538bd59 | 2020-11-04 20:46:08 -0800 | [diff] [blame] | 169 | GetStatusHelper raw(errmsg); | 
| Gilad Arnold | ae47a9a | 2014-03-26 12:16:47 -0700 | [diff] [blame] | 170 | if (!raw.is_success()) | 
| Alex Vakulenko | 88b591f | 2014-08-28 16:48:57 -0700 | [diff] [blame] | 171 | return nullptr; | 
| Gilad Arnold | ae47a9a | 2014-03-26 12:16:47 -0700 | [diff] [blame] | 172 |  | 
|  | 173 | for (auto& key_val : curr_op_str_to_stage) | 
|  | 174 | if (raw.update_status() == key_val.str) | 
|  | 175 | return new Stage(key_val.stage); | 
|  | 176 |  | 
|  | 177 | if (errmsg) | 
|  | 178 | *errmsg = string("Unknown update status: ") + raw.update_status(); | 
| Alex Vakulenko | 88b591f | 2014-08-28 16:48:57 -0700 | [diff] [blame] | 179 | return nullptr; | 
| Gilad Arnold | ae47a9a | 2014-03-26 12:16:47 -0700 | [diff] [blame] | 180 | } | 
|  | 181 |  | 
|  | 182 | // A variable reporting the version number that an update is updating to. | 
|  | 183 | class NewVersionVariable : public UpdaterVariableBase<string> { | 
|  | 184 | public: | 
| Amin Hassani | 538bd59 | 2020-11-04 20:46:08 -0800 | [diff] [blame] | 185 | explicit NewVersionVariable(const string& name) | 
|  | 186 | : UpdaterVariableBase<string>(name, kVariableModePoll) {} | 
| Gilad Arnold | ae47a9a | 2014-03-26 12:16:47 -0700 | [diff] [blame] | 187 |  | 
|  | 188 | private: | 
| Alex Vakulenko | 157fe30 | 2014-08-11 15:59:58 -0700 | [diff] [blame] | 189 | const string* GetValue(TimeDelta /* timeout */, string* errmsg) override { | 
| Amin Hassani | 538bd59 | 2020-11-04 20:46:08 -0800 | [diff] [blame] | 190 | GetStatusHelper raw(errmsg); | 
| Gilad Arnold | ae47a9a | 2014-03-26 12:16:47 -0700 | [diff] [blame] | 191 | if (!raw.is_success()) | 
| Alex Vakulenko | 88b591f | 2014-08-28 16:48:57 -0700 | [diff] [blame] | 192 | return nullptr; | 
| Gilad Arnold | ae47a9a | 2014-03-26 12:16:47 -0700 | [diff] [blame] | 193 |  | 
|  | 194 | return new string(raw.new_version()); | 
|  | 195 | } | 
|  | 196 |  | 
|  | 197 | DISALLOW_COPY_AND_ASSIGN(NewVersionVariable); | 
|  | 198 | }; | 
|  | 199 |  | 
|  | 200 | // A variable reporting the size of the update being processed in bytes. | 
| Aaron Wood | 7f92e2b | 2017-08-28 14:51:21 -0700 | [diff] [blame] | 201 | class PayloadSizeVariable : public UpdaterVariableBase<uint64_t> { | 
| Gilad Arnold | ae47a9a | 2014-03-26 12:16:47 -0700 | [diff] [blame] | 202 | public: | 
| Amin Hassani | 538bd59 | 2020-11-04 20:46:08 -0800 | [diff] [blame] | 203 | explicit PayloadSizeVariable(const string& name) | 
|  | 204 | : UpdaterVariableBase<uint64_t>(name, kVariableModePoll) {} | 
| Gilad Arnold | ae47a9a | 2014-03-26 12:16:47 -0700 | [diff] [blame] | 205 |  | 
|  | 206 | private: | 
| Aaron Wood | 7f92e2b | 2017-08-28 14:51:21 -0700 | [diff] [blame] | 207 | const uint64_t* GetValue(TimeDelta /* timeout */, string* errmsg) override { | 
| Amin Hassani | 538bd59 | 2020-11-04 20:46:08 -0800 | [diff] [blame] | 208 | GetStatusHelper raw(errmsg); | 
| Gilad Arnold | ae47a9a | 2014-03-26 12:16:47 -0700 | [diff] [blame] | 209 | if (!raw.is_success()) | 
| Alex Vakulenko | 88b591f | 2014-08-28 16:48:57 -0700 | [diff] [blame] | 210 | return nullptr; | 
| Gilad Arnold | ae47a9a | 2014-03-26 12:16:47 -0700 | [diff] [blame] | 211 |  | 
| Aaron Wood | 7f92e2b | 2017-08-28 14:51:21 -0700 | [diff] [blame] | 212 | return new uint64_t(raw.payload_size()); | 
| Gilad Arnold | ae47a9a | 2014-03-26 12:16:47 -0700 | [diff] [blame] | 213 | } | 
|  | 214 |  | 
|  | 215 | DISALLOW_COPY_AND_ASSIGN(PayloadSizeVariable); | 
|  | 216 | }; | 
|  | 217 |  | 
|  | 218 | // A variable reporting the point in time an update last completed in the | 
|  | 219 | // current boot cycle. | 
|  | 220 | // | 
|  | 221 | // TODO(garnold) In general, both the current boottime and wallclock time | 
|  | 222 | // readings should come from the time provider and be moderated by the | 
|  | 223 | // evaluation context, so that they are uniform throughout the evaluation of a | 
|  | 224 | // policy request. | 
|  | 225 | class UpdateCompletedTimeVariable : public UpdaterVariableBase<Time> { | 
|  | 226 | public: | 
| Amin Hassani | 538bd59 | 2020-11-04 20:46:08 -0800 | [diff] [blame] | 227 | explicit UpdateCompletedTimeVariable(const string& name) | 
|  | 228 | : UpdaterVariableBase<Time>(name, kVariableModePoll) {} | 
| Gilad Arnold | ae47a9a | 2014-03-26 12:16:47 -0700 | [diff] [blame] | 229 |  | 
|  | 230 | private: | 
| Alex Vakulenko | 157fe30 | 2014-08-11 15:59:58 -0700 | [diff] [blame] | 231 | const Time* GetValue(TimeDelta /* timeout */, string* errmsg) override { | 
| Gilad Arnold | ae47a9a | 2014-03-26 12:16:47 -0700 | [diff] [blame] | 232 | Time update_boottime; | 
| Amin Hassani | 538bd59 | 2020-11-04 20:46:08 -0800 | [diff] [blame] | 233 | if (!SystemState::Get()->update_attempter()->GetBootTimeAtUpdate( | 
| Gilad Arnold | ae47a9a | 2014-03-26 12:16:47 -0700 | [diff] [blame] | 234 | &update_boottime)) { | 
|  | 235 | if (errmsg) | 
|  | 236 | *errmsg = "Update completed time could not be read"; | 
| Alex Vakulenko | 88b591f | 2014-08-28 16:48:57 -0700 | [diff] [blame] | 237 | return nullptr; | 
| Gilad Arnold | ae47a9a | 2014-03-26 12:16:47 -0700 | [diff] [blame] | 238 | } | 
|  | 239 |  | 
| Amin Hassani | 0468a76 | 2020-11-17 23:53:48 -0800 | [diff] [blame] | 240 | const auto* clock = SystemState::Get()->clock(); | 
| Gilad Arnold | ae47a9a | 2014-03-26 12:16:47 -0700 | [diff] [blame] | 241 | Time curr_boottime = clock->GetBootTime(); | 
|  | 242 | if (curr_boottime < update_boottime) { | 
|  | 243 | if (errmsg) | 
|  | 244 | *errmsg = "Update completed time more recent than current time"; | 
| Alex Vakulenko | 88b591f | 2014-08-28 16:48:57 -0700 | [diff] [blame] | 245 | return nullptr; | 
| Gilad Arnold | ae47a9a | 2014-03-26 12:16:47 -0700 | [diff] [blame] | 246 | } | 
|  | 247 | TimeDelta duration_since_update = curr_boottime - update_boottime; | 
|  | 248 | return new Time(clock->GetWallclockTime() - duration_since_update); | 
|  | 249 | } | 
|  | 250 |  | 
|  | 251 | DISALLOW_COPY_AND_ASSIGN(UpdateCompletedTimeVariable); | 
|  | 252 | }; | 
|  | 253 |  | 
|  | 254 | // Variables reporting the current image channel. | 
|  | 255 | class CurrChannelVariable : public UpdaterVariableBase<string> { | 
|  | 256 | public: | 
| Amin Hassani | 538bd59 | 2020-11-04 20:46:08 -0800 | [diff] [blame] | 257 | explicit CurrChannelVariable(const string& name) | 
|  | 258 | : UpdaterVariableBase<string>(name, kVariableModePoll) {} | 
| Gilad Arnold | ae47a9a | 2014-03-26 12:16:47 -0700 | [diff] [blame] | 259 |  | 
|  | 260 | private: | 
| Alex Vakulenko | 157fe30 | 2014-08-11 15:59:58 -0700 | [diff] [blame] | 261 | const string* GetValue(TimeDelta /* timeout */, string* errmsg) override { | 
| Amin Hassani | 538bd59 | 2020-11-04 20:46:08 -0800 | [diff] [blame] | 262 | OmahaRequestParams* request_params = SystemState::Get()->request_params(); | 
| Gilad Arnold | ae47a9a | 2014-03-26 12:16:47 -0700 | [diff] [blame] | 263 | string channel = request_params->current_channel(); | 
|  | 264 | if (channel.empty()) { | 
|  | 265 | if (errmsg) | 
|  | 266 | *errmsg = "No current channel"; | 
| Alex Vakulenko | 88b591f | 2014-08-28 16:48:57 -0700 | [diff] [blame] | 267 | return nullptr; | 
| Gilad Arnold | ae47a9a | 2014-03-26 12:16:47 -0700 | [diff] [blame] | 268 | } | 
|  | 269 | return new string(channel); | 
|  | 270 | } | 
|  | 271 |  | 
|  | 272 | DISALLOW_COPY_AND_ASSIGN(CurrChannelVariable); | 
|  | 273 | }; | 
|  | 274 |  | 
|  | 275 | // Variables reporting the new image channel. | 
|  | 276 | class NewChannelVariable : public UpdaterVariableBase<string> { | 
|  | 277 | public: | 
| Amin Hassani | 538bd59 | 2020-11-04 20:46:08 -0800 | [diff] [blame] | 278 | explicit NewChannelVariable(const string& name) | 
|  | 279 | : UpdaterVariableBase<string>(name, kVariableModePoll) {} | 
| Gilad Arnold | ae47a9a | 2014-03-26 12:16:47 -0700 | [diff] [blame] | 280 |  | 
|  | 281 | private: | 
| Alex Vakulenko | 157fe30 | 2014-08-11 15:59:58 -0700 | [diff] [blame] | 282 | const string* GetValue(TimeDelta /* timeout */, string* errmsg) override { | 
| Amin Hassani | 538bd59 | 2020-11-04 20:46:08 -0800 | [diff] [blame] | 283 | OmahaRequestParams* request_params = SystemState::Get()->request_params(); | 
| Gilad Arnold | ae47a9a | 2014-03-26 12:16:47 -0700 | [diff] [blame] | 284 | string channel = request_params->target_channel(); | 
|  | 285 | if (channel.empty()) { | 
|  | 286 | if (errmsg) | 
|  | 287 | *errmsg = "No new channel"; | 
| Alex Vakulenko | 88b591f | 2014-08-28 16:48:57 -0700 | [diff] [blame] | 288 | return nullptr; | 
| Gilad Arnold | ae47a9a | 2014-03-26 12:16:47 -0700 | [diff] [blame] | 289 | } | 
|  | 290 | return new string(channel); | 
|  | 291 | } | 
|  | 292 |  | 
|  | 293 | DISALLOW_COPY_AND_ASSIGN(NewChannelVariable); | 
|  | 294 | }; | 
|  | 295 |  | 
|  | 296 | // A variable class for reading Boolean prefs values. | 
| Alex Deymo | d6f6007 | 2015-10-12 12:22:27 -0700 | [diff] [blame] | 297 | class BooleanPrefVariable | 
|  | 298 | : public AsyncCopyVariable<bool>, | 
|  | 299 | public chromeos_update_engine::PrefsInterface::ObserverInterface { | 
| Gilad Arnold | ae47a9a | 2014-03-26 12:16:47 -0700 | [diff] [blame] | 300 | public: | 
| Alex Deymo | d6f6007 | 2015-10-12 12:22:27 -0700 | [diff] [blame] | 301 | BooleanPrefVariable(const string& name, | 
| Alex Deymo | d6f6007 | 2015-10-12 12:22:27 -0700 | [diff] [blame] | 302 | const char* key, | 
|  | 303 | bool default_val) | 
|  | 304 | : AsyncCopyVariable<bool>(name), | 
| Alex Deymo | d6f6007 | 2015-10-12 12:22:27 -0700 | [diff] [blame] | 305 | key_(key), | 
|  | 306 | default_val_(default_val) { | 
| Amin Hassani | 90e9f19 | 2020-11-18 14:20:56 -0800 | [diff] [blame] | 307 | SystemState::Get()->prefs()->AddObserver(key, this); | 
| Alex Deymo | d6f6007 | 2015-10-12 12:22:27 -0700 | [diff] [blame] | 308 | OnPrefSet(key); | 
|  | 309 | } | 
| Amin Hassani | 90e9f19 | 2020-11-18 14:20:56 -0800 | [diff] [blame] | 310 | ~BooleanPrefVariable() { | 
|  | 311 | SystemState::Get()->prefs()->RemoveObserver(key_, this); | 
|  | 312 | } | 
| Gilad Arnold | ae47a9a | 2014-03-26 12:16:47 -0700 | [diff] [blame] | 313 |  | 
|  | 314 | private: | 
| Alex Deymo | d6f6007 | 2015-10-12 12:22:27 -0700 | [diff] [blame] | 315 | // Reads the actual value from the Prefs instance and updates the Variable | 
|  | 316 | // value. | 
|  | 317 | void OnPrefSet(const string& key) override { | 
| Gilad Arnold | ae47a9a | 2014-03-26 12:16:47 -0700 | [diff] [blame] | 318 | bool result = default_val_; | 
| Amin Hassani | 90e9f19 | 2020-11-18 14:20:56 -0800 | [diff] [blame] | 319 | auto* prefs = SystemState::Get()->prefs(); | 
|  | 320 | if (prefs->Exists(key_) && !prefs->GetBoolean(key_, &result)) | 
| Alex Deymo | d6f6007 | 2015-10-12 12:22:27 -0700 | [diff] [blame] | 321 | result = default_val_; | 
|  | 322 | // AsyncCopyVariable will take care of values that didn't change. | 
|  | 323 | SetValue(result); | 
| Gilad Arnold | ae47a9a | 2014-03-26 12:16:47 -0700 | [diff] [blame] | 324 | } | 
|  | 325 |  | 
| Amin Hassani | 4b71743 | 2019-01-14 16:24:20 -0800 | [diff] [blame] | 326 | void OnPrefDeleted(const string& key) override { SetValue(default_val_); } | 
| Alex Deymo | d6f6007 | 2015-10-12 12:22:27 -0700 | [diff] [blame] | 327 |  | 
| Gilad Arnold | ae47a9a | 2014-03-26 12:16:47 -0700 | [diff] [blame] | 328 | // The Boolean preference key and default value. | 
|  | 329 | const char* const key_; | 
|  | 330 | const bool default_val_; | 
|  | 331 |  | 
|  | 332 | DISALLOW_COPY_AND_ASSIGN(BooleanPrefVariable); | 
|  | 333 | }; | 
|  | 334 |  | 
| Gilad Arnold | a6dab94 | 2014-04-25 11:46:03 -0700 | [diff] [blame] | 335 | // A variable returning the number of consecutive failed update checks. | 
| Gilad Arnold | cf175a0 | 2014-07-10 16:48:47 -0700 | [diff] [blame] | 336 | class ConsecutiveFailedUpdateChecksVariable | 
|  | 337 | : public UpdaterVariableBase<unsigned int> { | 
| Gilad Arnold | a6dab94 | 2014-04-25 11:46:03 -0700 | [diff] [blame] | 338 | public: | 
| Amin Hassani | 538bd59 | 2020-11-04 20:46:08 -0800 | [diff] [blame] | 339 | explicit ConsecutiveFailedUpdateChecksVariable(const string& name) | 
|  | 340 | : UpdaterVariableBase<unsigned int>(name, kVariableModePoll) {} | 
| Gilad Arnold | a6dab94 | 2014-04-25 11:46:03 -0700 | [diff] [blame] | 341 |  | 
|  | 342 | private: | 
| Alex Vakulenko | 157fe30 | 2014-08-11 15:59:58 -0700 | [diff] [blame] | 343 | const unsigned int* GetValue(TimeDelta /* timeout */, | 
|  | 344 | string* /* errmsg */) override { | 
| Amin Hassani | 538bd59 | 2020-11-04 20:46:08 -0800 | [diff] [blame] | 345 | // NOLINTNEXTLINE(readability/casting) | 
|  | 346 | return new unsigned int(SystemState::Get() | 
|  | 347 | ->update_attempter() | 
|  | 348 | ->consecutive_failed_update_checks()); | 
| Gilad Arnold | a6dab94 | 2014-04-25 11:46:03 -0700 | [diff] [blame] | 349 | } | 
|  | 350 |  | 
|  | 351 | DISALLOW_COPY_AND_ASSIGN(ConsecutiveFailedUpdateChecksVariable); | 
|  | 352 | }; | 
| Gilad Arnold | ae47a9a | 2014-03-26 12:16:47 -0700 | [diff] [blame] | 353 |  | 
| Gilad Arnold | a0258a5 | 2014-07-10 16:21:19 -0700 | [diff] [blame] | 354 | // A variable returning the server-dictated poll interval. | 
|  | 355 | class ServerDictatedPollIntervalVariable | 
|  | 356 | : public UpdaterVariableBase<unsigned int> { | 
|  | 357 | public: | 
| Amin Hassani | 538bd59 | 2020-11-04 20:46:08 -0800 | [diff] [blame] | 358 | explicit ServerDictatedPollIntervalVariable(const string& name) | 
|  | 359 | : UpdaterVariableBase<unsigned int>(name, kVariableModePoll) {} | 
| Gilad Arnold | a0258a5 | 2014-07-10 16:21:19 -0700 | [diff] [blame] | 360 |  | 
|  | 361 | private: | 
| Alex Vakulenko | 157fe30 | 2014-08-11 15:59:58 -0700 | [diff] [blame] | 362 | const unsigned int* GetValue(TimeDelta /* timeout */, | 
|  | 363 | string* /* errmsg */) override { | 
| Amin Hassani | 538bd59 | 2020-11-04 20:46:08 -0800 | [diff] [blame] | 364 | // NOLINTNEXTLINE(readability/casting) | 
|  | 365 | return new unsigned int(SystemState::Get() | 
|  | 366 | ->update_attempter() | 
|  | 367 | ->server_dictated_poll_interval()); | 
| Gilad Arnold | a0258a5 | 2014-07-10 16:21:19 -0700 | [diff] [blame] | 368 | } | 
|  | 369 |  | 
|  | 370 | DISALLOW_COPY_AND_ASSIGN(ServerDictatedPollIntervalVariable); | 
|  | 371 | }; | 
|  | 372 |  | 
| Gilad Arnold | ec7f916 | 2014-07-15 13:24:46 -0700 | [diff] [blame] | 373 | // An async variable that tracks changes to forced update requests. | 
|  | 374 | class ForcedUpdateRequestedVariable | 
|  | 375 | : public UpdaterVariableBase<UpdateRequestStatus> { | 
| Gilad Arnold | 44dc3bf | 2014-07-18 23:39:38 -0700 | [diff] [blame] | 376 | public: | 
| Amin Hassani | 538bd59 | 2020-11-04 20:46:08 -0800 | [diff] [blame] | 377 | explicit ForcedUpdateRequestedVariable(const string& name) | 
| Gilad Arnold | ec7f916 | 2014-07-15 13:24:46 -0700 | [diff] [blame] | 378 | : UpdaterVariableBase<UpdateRequestStatus>::UpdaterVariableBase( | 
| Amin Hassani | 538bd59 | 2020-11-04 20:46:08 -0800 | [diff] [blame] | 379 | name, kVariableModeAsync) { | 
|  | 380 | SystemState::Get()->update_attempter()->set_forced_update_pending_callback( | 
| Gilad Arnold | ec7f916 | 2014-07-15 13:24:46 -0700 | [diff] [blame] | 381 | new base::Callback<void(bool, bool)>(  // NOLINT(readability/function) | 
|  | 382 | base::Bind(&ForcedUpdateRequestedVariable::Reset, | 
| Gilad Arnold | 44dc3bf | 2014-07-18 23:39:38 -0700 | [diff] [blame] | 383 | base::Unretained(this)))); | 
|  | 384 | } | 
|  | 385 |  | 
|  | 386 | private: | 
| Gilad Arnold | ec7f916 | 2014-07-15 13:24:46 -0700 | [diff] [blame] | 387 | const UpdateRequestStatus* GetValue(TimeDelta /* timeout */, | 
|  | 388 | string* /* errmsg */) override { | 
|  | 389 | return new UpdateRequestStatus(update_request_status_); | 
| Gilad Arnold | 44dc3bf | 2014-07-18 23:39:38 -0700 | [diff] [blame] | 390 | } | 
|  | 391 |  | 
| Amin Hassani | ed37d68 | 2018-04-06 13:22:00 -0700 | [diff] [blame] | 392 | void Reset(bool forced_update_requested, bool interactive) { | 
| Gilad Arnold | ec7f916 | 2014-07-15 13:24:46 -0700 | [diff] [blame] | 393 | UpdateRequestStatus new_value = UpdateRequestStatus::kNone; | 
|  | 394 | if (forced_update_requested) | 
| Amin Hassani | ed37d68 | 2018-04-06 13:22:00 -0700 | [diff] [blame] | 395 | new_value = (interactive ? UpdateRequestStatus::kInteractive | 
|  | 396 | : UpdateRequestStatus::kPeriodic); | 
| Gilad Arnold | ec7f916 | 2014-07-15 13:24:46 -0700 | [diff] [blame] | 397 | if (update_request_status_ != new_value) { | 
|  | 398 | update_request_status_ = new_value; | 
| Gilad Arnold | 44dc3bf | 2014-07-18 23:39:38 -0700 | [diff] [blame] | 399 | NotifyValueChanged(); | 
|  | 400 | } | 
|  | 401 | } | 
|  | 402 |  | 
| Gilad Arnold | ec7f916 | 2014-07-15 13:24:46 -0700 | [diff] [blame] | 403 | UpdateRequestStatus update_request_status_ = UpdateRequestStatus::kNone; | 
| Gilad Arnold | 44dc3bf | 2014-07-18 23:39:38 -0700 | [diff] [blame] | 404 |  | 
| Gilad Arnold | ec7f916 | 2014-07-15 13:24:46 -0700 | [diff] [blame] | 405 | DISALLOW_COPY_AND_ASSIGN(ForcedUpdateRequestedVariable); | 
| Gilad Arnold | 44dc3bf | 2014-07-18 23:39:38 -0700 | [diff] [blame] | 406 | }; | 
|  | 407 |  | 
| Aaron Wood | bf5a252 | 2017-10-04 10:58:36 -0700 | [diff] [blame] | 408 | // A variable returning the current update restrictions that are in effect. | 
|  | 409 | class UpdateRestrictionsVariable | 
|  | 410 | : public UpdaterVariableBase<UpdateRestrictions> { | 
|  | 411 | public: | 
| Amin Hassani | 538bd59 | 2020-11-04 20:46:08 -0800 | [diff] [blame] | 412 | explicit UpdateRestrictionsVariable(const string& name) | 
|  | 413 | : UpdaterVariableBase<UpdateRestrictions>(name, kVariableModePoll) {} | 
| Aaron Wood | bf5a252 | 2017-10-04 10:58:36 -0700 | [diff] [blame] | 414 |  | 
|  | 415 | private: | 
|  | 416 | const UpdateRestrictions* GetValue(TimeDelta /* timeout */, | 
|  | 417 | string* /* errmsg */) override { | 
|  | 418 | UpdateAttemptFlags attempt_flags = | 
| Amin Hassani | 538bd59 | 2020-11-04 20:46:08 -0800 | [diff] [blame] | 419 | SystemState::Get()->update_attempter()->GetCurrentUpdateAttemptFlags(); | 
| Aaron Wood | bf5a252 | 2017-10-04 10:58:36 -0700 | [diff] [blame] | 420 | UpdateRestrictions restriction_flags = UpdateRestrictions::kNone; | 
|  | 421 | // Don't blindly copy the whole value, test and set bits that should | 
|  | 422 | // transfer from one set of flags to the other. | 
|  | 423 | if (attempt_flags & UpdateAttemptFlags::kFlagRestrictDownload) { | 
|  | 424 | restriction_flags = static_cast<UpdateRestrictions>( | 
|  | 425 | restriction_flags | UpdateRestrictions::kRestrictDownloading); | 
|  | 426 | } | 
|  | 427 |  | 
|  | 428 | return new UpdateRestrictions(restriction_flags); | 
|  | 429 | } | 
|  | 430 |  | 
|  | 431 | DISALLOW_COPY_AND_ASSIGN(UpdateRestrictionsVariable); | 
|  | 432 | }; | 
|  | 433 |  | 
| Amin Hassani | 03277de | 2020-07-28 12:32:49 -0700 | [diff] [blame] | 434 | // A variable class for reading timeout interval prefs value. | 
|  | 435 | class TestUpdateCheckIntervalTimeoutVariable : public Variable<int64_t> { | 
|  | 436 | public: | 
| Amin Hassani | 90e9f19 | 2020-11-18 14:20:56 -0800 | [diff] [blame] | 437 | explicit TestUpdateCheckIntervalTimeoutVariable(const string& name) | 
|  | 438 | : Variable<int64_t>(name, kVariableModePoll), read_count_(0) { | 
| Amin Hassani | 03277de | 2020-07-28 12:32:49 -0700 | [diff] [blame] | 439 | SetMissingOk(); | 
|  | 440 | } | 
|  | 441 | ~TestUpdateCheckIntervalTimeoutVariable() = default; | 
|  | 442 |  | 
|  | 443 | private: | 
|  | 444 | const int64_t* GetValue(TimeDelta /* timeout */, | 
|  | 445 | string* /* errmsg */) override { | 
|  | 446 | auto key = chromeos_update_engine::kPrefsTestUpdateCheckIntervalTimeout; | 
| Amin Hassani | 90e9f19 | 2020-11-18 14:20:56 -0800 | [diff] [blame] | 447 | auto* prefs = SystemState::Get()->prefs(); | 
| Amin Hassani | 03277de | 2020-07-28 12:32:49 -0700 | [diff] [blame] | 448 | int64_t result; | 
| Amin Hassani | 90e9f19 | 2020-11-18 14:20:56 -0800 | [diff] [blame] | 449 | if (prefs->Exists(key) && prefs->GetInt64(key, &result)) { | 
| Amin Hassani | 03277de | 2020-07-28 12:32:49 -0700 | [diff] [blame] | 450 | // This specific value is used for testing only. So it should not be kept | 
|  | 451 | // around and should be deleted after a few reads. | 
| Amin Hassani | 7ad016b | 2020-09-03 14:19:13 -0700 | [diff] [blame] | 452 | if (++read_count_ > 5) | 
| Amin Hassani | 90e9f19 | 2020-11-18 14:20:56 -0800 | [diff] [blame] | 453 | prefs->Delete(key); | 
| Amin Hassani | 03277de | 2020-07-28 12:32:49 -0700 | [diff] [blame] | 454 |  | 
|  | 455 | // Limit the timeout interval to 10 minutes so it is not abused if it is | 
|  | 456 | // seen on official images. | 
|  | 457 | return new int64_t(std::min(result, static_cast<int64_t>(10 * 60))); | 
|  | 458 | } | 
|  | 459 | return nullptr; | 
|  | 460 | } | 
|  | 461 |  | 
| Amin Hassani | 03277de | 2020-07-28 12:32:49 -0700 | [diff] [blame] | 462 | // Counts how many times this variable is read. This is used to delete the | 
|  | 463 | // underlying file defining the variable after a certain number of reads in | 
|  | 464 | // order to prevent any abuse of this variable. | 
|  | 465 | int read_count_; | 
|  | 466 |  | 
|  | 467 | DISALLOW_COPY_AND_ASSIGN(TestUpdateCheckIntervalTimeoutVariable); | 
|  | 468 | }; | 
|  | 469 |  | 
| Gilad Arnold | ae47a9a | 2014-03-26 12:16:47 -0700 | [diff] [blame] | 470 | // RealUpdaterProvider methods. | 
|  | 471 |  | 
| Amin Hassani | 538bd59 | 2020-11-04 20:46:08 -0800 | [diff] [blame] | 472 | RealUpdaterProvider::RealUpdaterProvider() | 
|  | 473 | : var_updater_started_time_( | 
|  | 474 | "updater_started_time", | 
|  | 475 | SystemState::Get()->clock()->GetWallclockTime()), | 
|  | 476 | var_last_checked_time_(new LastCheckedTimeVariable("last_checked_time")), | 
|  | 477 | var_update_completed_time_( | 
|  | 478 | new UpdateCompletedTimeVariable("update_completed_time")), | 
|  | 479 | var_progress_(new ProgressVariable("progress")), | 
|  | 480 | var_stage_(new StageVariable("stage")), | 
|  | 481 | var_new_version_(new NewVersionVariable("new_version")), | 
|  | 482 | var_payload_size_(new PayloadSizeVariable("payload_size")), | 
|  | 483 | var_curr_channel_(new CurrChannelVariable("curr_channel")), | 
|  | 484 | var_new_channel_(new NewChannelVariable("new_channel")), | 
| Amin Hassani | 90e9f19 | 2020-11-18 14:20:56 -0800 | [diff] [blame] | 485 | var_p2p_enabled_(new BooleanPrefVariable( | 
|  | 486 | "p2p_enabled", chromeos_update_engine::kPrefsP2PEnabled, false)), | 
| Aaron Wood | bf5a252 | 2017-10-04 10:58:36 -0700 | [diff] [blame] | 487 | var_cellular_enabled_(new BooleanPrefVariable( | 
|  | 488 | "cellular_enabled", | 
| Aaron Wood | bf5a252 | 2017-10-04 10:58:36 -0700 | [diff] [blame] | 489 | chromeos_update_engine::kPrefsUpdateOverCellularPermission, | 
|  | 490 | false)), | 
|  | 491 | var_consecutive_failed_update_checks_( | 
|  | 492 | new ConsecutiveFailedUpdateChecksVariable( | 
| Amin Hassani | 538bd59 | 2020-11-04 20:46:08 -0800 | [diff] [blame] | 493 | "consecutive_failed_update_checks")), | 
| Aaron Wood | bf5a252 | 2017-10-04 10:58:36 -0700 | [diff] [blame] | 494 | var_server_dictated_poll_interval_(new ServerDictatedPollIntervalVariable( | 
| Amin Hassani | 538bd59 | 2020-11-04 20:46:08 -0800 | [diff] [blame] | 495 | "server_dictated_poll_interval")), | 
|  | 496 | var_forced_update_requested_( | 
|  | 497 | new ForcedUpdateRequestedVariable("forced_update_requested")), | 
| Amin Hassani | 03277de | 2020-07-28 12:32:49 -0700 | [diff] [blame] | 498 | var_update_restrictions_( | 
| Amin Hassani | 538bd59 | 2020-11-04 20:46:08 -0800 | [diff] [blame] | 499 | new UpdateRestrictionsVariable("update_restrictions")), | 
| Amin Hassani | 03277de | 2020-07-28 12:32:49 -0700 | [diff] [blame] | 500 | var_test_update_check_interval_timeout_( | 
|  | 501 | new TestUpdateCheckIntervalTimeoutVariable( | 
| Amin Hassani | 90e9f19 | 2020-11-18 14:20:56 -0800 | [diff] [blame] | 502 | "test_update_check_interval_timeout")) {} | 
| Alex Deymo | 63784a5 | 2014-05-28 10:46:14 -0700 | [diff] [blame] | 503 | }  // namespace chromeos_update_manager |