blob: e3e968b7e51b4f1cc3127ebda5f9af5fe6ea94db [file] [log] [blame]
sorin30474f02017-04-27 00:45:481// 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 COMPONENTS_UPDATE_CLIENT_COMPONENT_H_
6#define COMPONENTS_UPDATE_CLIENT_COMPONENT_H_
7
8#include <map>
9#include <memory>
10#include <string>
11#include <utility>
12#include <vector>
13
14#include "base/callback.h"
15#include "base/files/file_path.h"
16#include "base/gtest_prod_util.h"
17#include "base/macros.h"
18#include "base/memory/ref_counted.h"
Sorin Jianu888ec292018-06-01 15:35:4219#include "base/optional.h"
sorin30474f02017-04-27 00:45:4820#include "base/threading/thread_checker.h"
21#include "base/time/time.h"
22#include "base/version.h"
sorin30474f02017-04-27 00:45:4823#include "components/update_client/crx_downloader.h"
sorin7cff6e52017-05-17 16:37:2324#include "components/update_client/protocol_parser.h"
sorin30474f02017-04-27 00:45:4825#include "components/update_client/update_client.h"
sorin30474f02017-04-27 00:45:4826#include "url/gurl.h"
27
Sorin Jianu039032b2018-10-12 21:48:1328namespace base {
29class Value;
30} // namespace base
sorin30474f02017-04-27 00:45:4831
32namespace update_client {
33
Sorin Jianu4ab7c292017-06-15 18:40:2134class ActionRunner;
Sorin Jianub3296162017-12-13 20:26:3235class Configurator;
sorin30474f02017-04-27 00:45:4836struct CrxUpdateItem;
37struct UpdateContext;
38
39// Describes a CRX component managed by the UpdateEngine. Each |Component| is
40// associated with an UpdateContext.
41class Component {
42 public:
43 using Events = UpdateClient::Observer::Events;
44
Sorin Jianua8ef73d2017-11-02 16:55:1745 using CallbackHandleComplete = base::OnceCallback<void()>;
sorin30474f02017-04-27 00:45:4846
47 Component(const UpdateContext& update_context, const std::string& id);
48 ~Component();
49
50 // Handles the current state of the component and makes it transition
Sorin Jianuee5c0db2018-04-12 23:38:4751 // to the next component state before |callback_handle_complete_| is invoked.
52 void Handle(CallbackHandleComplete callback_handle_complete);
sorin30474f02017-04-27 00:45:4853
54 CrxUpdateItem GetCrxUpdateItem() const;
55
sorin30474f02017-04-27 00:45:4856 // Sets the uninstall state for this component.
57 void Uninstall(const base::Version& cur_version, int reason);
58
59 // Called by the UpdateEngine when an update check for this component is done.
Sorin Jianu888ec292018-06-01 15:35:4260 void SetUpdateCheckResult(
61 const base::Optional<ProtocolParser::Result>& result,
62 ErrorCategory error_category,
63 int error);
sorin30474f02017-04-27 00:45:4864
65 // Returns true if the component has reached a final state and no further
66 // handling and state transitions are possible.
Sorin Jianuee5c0db2018-04-12 23:38:4767 bool IsHandled() const { return is_handled_; }
sorin30474f02017-04-27 00:45:4868
69 // Returns true if an update is available for this component, meaning that
70 // the update server has return a response containing an update.
71 bool IsUpdateAvailable() const { return is_update_available_; }
72
sorin30474f02017-04-27 00:45:4873 base::TimeDelta GetUpdateDuration() const;
74
75 ComponentState state() const { return state_->state(); }
76
77 std::string id() const { return id_; }
78
Sorin Jianu73900242018-08-17 01:11:5379 const base::Optional<CrxComponent>& crx_component() const {
80 return crx_component_;
81 }
82 void set_crx_component(const CrxComponent& crx_component) {
83 crx_component_ = crx_component;
sorin30474f02017-04-27 00:45:4884 }
85
86 const base::Version& previous_version() const { return previous_version_; }
87 void set_previous_version(const base::Version& previous_version) {
88 previous_version_ = previous_version;
89 }
90
91 const base::Version& next_version() const { return next_version_; }
92
93 std::string previous_fp() const { return previous_fp_; }
94 void set_previous_fp(const std::string& previous_fp) {
95 previous_fp_ = previous_fp;
96 }
97
98 std::string next_fp() const { return next_fp_; }
99 void set_next_fp(const std::string& next_fp) { next_fp_ = next_fp; }
100
Sorin Jianub41a592a2018-03-02 16:30:27101 bool is_foreground() const;
sorin30474f02017-04-27 00:45:48102
sorin30474f02017-04-27 00:45:48103 const std::vector<GURL>& crx_diffurls() const { return crx_diffurls_; }
104
105 bool diff_update_failed() const { return !!diff_error_code_; }
106
Minh X. Nguyena4640cb2018-05-23 21:29:10107 ErrorCategory error_category() const { return error_category_; }
sorin30474f02017-04-27 00:45:48108 int error_code() const { return error_code_; }
109 int extra_code1() const { return extra_code1_; }
Minh X. Nguyena4640cb2018-05-23 21:29:10110 ErrorCategory diff_error_category() const { return diff_error_category_; }
sorin30474f02017-04-27 00:45:48111 int diff_error_code() const { return diff_error_code_; }
112 int diff_extra_code1() const { return diff_extra_code1_; }
113
Sorin Jianu4ab7c292017-06-15 18:40:21114 std::string action_run() const { return action_run_; }
115
Sorin Jianub3296162017-12-13 20:26:32116 scoped_refptr<Configurator> config() const;
117
Sorin Jianud69d4372018-02-07 19:44:22118 std::string session_id() const;
119
Sorin Jianu039032b2018-10-12 21:48:13120 const std::vector<base::Value>& events() const { return events_; }
121
122 // Returns a clone of the component events.
123 std::vector<base::Value> GetEvents() const;
124
sorin30474f02017-04-27 00:45:48125 private:
Sorin Jianua8926bf2018-03-09 21:02:53126 friend class MockPingManagerImpl;
sorin30474f02017-04-27 00:45:48127 friend class UpdateCheckerTest;
128
129 FRIEND_TEST_ALL_PREFIXES(PingManagerTest, SendPing);
130 FRIEND_TEST_ALL_PREFIXES(PingManagerTest, RequiresEncryption);
sorin519656c2017-04-28 22:39:34131 FRIEND_TEST_ALL_PREFIXES(UpdateCheckerTest, NoUpdateActionRun);
sorin30474f02017-04-27 00:45:48132 FRIEND_TEST_ALL_PREFIXES(UpdateCheckerTest, UpdateCheckCupError);
133 FRIEND_TEST_ALL_PREFIXES(UpdateCheckerTest, UpdateCheckError);
134 FRIEND_TEST_ALL_PREFIXES(UpdateCheckerTest, UpdateCheckInvalidAp);
135 FRIEND_TEST_ALL_PREFIXES(UpdateCheckerTest,
136 UpdateCheckRequiresEncryptionError);
137 FRIEND_TEST_ALL_PREFIXES(UpdateCheckerTest, UpdateCheckSuccess);
138 FRIEND_TEST_ALL_PREFIXES(UpdateCheckerTest, UpdateCheckUpdateDisabled);
139
140 // Describes an abstraction for implementing the behavior of a component and
141 // the transition from one state to another.
142 class State {
143 public:
144 using CallbackNextState =
Sorin Jianua8ef73d2017-11-02 16:55:17145 base::OnceCallback<void(std::unique_ptr<State> next_state)>;
sorin30474f02017-04-27 00:45:48146
147 State(Component* component, ComponentState state);
148 virtual ~State();
149
150 // Handles the current state and initiates a transition to a new state.
151 // The transition to the new state is non-blocking and it is completed
152 // by the outer component, after the current state is fully handled.
153 void Handle(CallbackNextState callback);
154
155 ComponentState state() const { return state_; }
156
sorin30474f02017-04-27 00:45:48157 protected:
158 // Initiates the transition to the new state.
159 void TransitionState(std::unique_ptr<State> new_state);
160
Sorin Jianuee5c0db2018-04-12 23:38:47161 // Makes the current state a final state where no other state transition
162 // can further occur.
163 void EndState();
164
sorin30474f02017-04-27 00:45:48165 Component& component() { return component_; }
166 const Component& component() const { return component_; }
167
sorin30474f02017-04-27 00:45:48168 base::ThreadChecker thread_checker_;
169
170 const ComponentState state_;
171
172 private:
173 virtual void DoHandle() = 0;
174
175 Component& component_;
Sorin Jianuee5c0db2018-04-12 23:38:47176 CallbackNextState callback_next_state_;
sorin30474f02017-04-27 00:45:48177 };
178
179 class StateNew : public State {
180 public:
181 explicit StateNew(Component* component);
182 ~StateNew() override;
183
184 private:
185 // State overrides.
186 void DoHandle() override;
187
188 DISALLOW_COPY_AND_ASSIGN(StateNew);
189 };
190
191 class StateChecking : public State {
192 public:
193 explicit StateChecking(Component* component);
194 ~StateChecking() override;
195
196 private:
197 // State overrides.
198 void DoHandle() override;
199
200 void UpdateCheckComplete();
201
202 DISALLOW_COPY_AND_ASSIGN(StateChecking);
203 };
204
205 class StateUpdateError : public State {
206 public:
207 explicit StateUpdateError(Component* component);
208 ~StateUpdateError() override;
209
210 private:
211 // State overrides.
212 void DoHandle() override;
213
214 DISALLOW_COPY_AND_ASSIGN(StateUpdateError);
215 };
216
217 class StateCanUpdate : public State {
218 public:
219 explicit StateCanUpdate(Component* component);
220 ~StateCanUpdate() override;
221
222 private:
223 // State overrides.
224 void DoHandle() override;
225 bool CanTryDiffUpdate() const;
226
227 DISALLOW_COPY_AND_ASSIGN(StateCanUpdate);
228 };
229
230 class StateUpToDate : public State {
231 public:
232 explicit StateUpToDate(Component* component);
233 ~StateUpToDate() override;
234
235 private:
236 // State overrides.
237 void DoHandle() override;
238
239 DISALLOW_COPY_AND_ASSIGN(StateUpToDate);
240 };
241
242 class StateDownloadingDiff : public State {
243 public:
244 explicit StateDownloadingDiff(Component* component);
245 ~StateDownloadingDiff() override;
246
247 private:
248 // State overrides.
249 void DoHandle() override;
250
Antonio Gomes31237fb2018-08-27 19:11:03251 // Called when progress is being made downloading a CRX. Can be called
252 // multiple times due to how the CRX downloader switches between
sorin30474f02017-04-27 00:45:48253 // different downloaders and fallback urls.
Antonio Gomes31237fb2018-08-27 19:11:03254 void DownloadProgress(const std::string& id);
sorin30474f02017-04-27 00:45:48255
256 void DownloadComplete(const std::string& id,
257 const CrxDownloader::Result& download_result);
258
259 // Downloads updates for one CRX id only.
260 std::unique_ptr<CrxDownloader> crx_downloader_;
261
262 DISALLOW_COPY_AND_ASSIGN(StateDownloadingDiff);
263 };
264
265 class StateDownloading : public State {
266 public:
267 explicit StateDownloading(Component* component);
268 ~StateDownloading() override;
269
270 private:
271 // State overrides.
272 void DoHandle() override;
273
Antonio Gomes31237fb2018-08-27 19:11:03274 // Called when progress is being made downloading a CRX. Can be called
275 // multiple times due to how the CRX downloader switches between
sorin30474f02017-04-27 00:45:48276 // different downloaders and fallback urls.
Antonio Gomes31237fb2018-08-27 19:11:03277 void DownloadProgress(const std::string& id);
sorin30474f02017-04-27 00:45:48278
279 void DownloadComplete(const std::string& id,
280 const CrxDownloader::Result& download_result);
281
282 // Downloads updates for one CRX id only.
283 std::unique_ptr<CrxDownloader> crx_downloader_;
284
285 DISALLOW_COPY_AND_ASSIGN(StateDownloading);
286 };
287
288 class StateUpdatingDiff : public State {
289 public:
290 explicit StateUpdatingDiff(Component* component);
291 ~StateUpdatingDiff() override;
292
293 private:
294 // State overrides.
295 void DoHandle() override;
296
Minh X. Nguyena4640cb2018-05-23 21:29:10297 void InstallComplete(ErrorCategory error_category,
298 int error_code,
299 int extra_code1);
sorin30474f02017-04-27 00:45:48300
301 DISALLOW_COPY_AND_ASSIGN(StateUpdatingDiff);
302 };
303
304 class StateUpdating : public State {
305 public:
306 explicit StateUpdating(Component* component);
307 ~StateUpdating() override;
308
309 private:
310 // State overrides.
311 void DoHandle() override;
312
Minh X. Nguyena4640cb2018-05-23 21:29:10313 void InstallComplete(ErrorCategory error_category,
314 int error_code,
315 int extra_code1);
sorin30474f02017-04-27 00:45:48316
sorin30474f02017-04-27 00:45:48317 DISALLOW_COPY_AND_ASSIGN(StateUpdating);
318 };
319
320 class StateUpdated : public State {
321 public:
322 explicit StateUpdated(Component* component);
323 ~StateUpdated() override;
324
325 private:
326 // State overrides.
327 void DoHandle() override;
328
329 DISALLOW_COPY_AND_ASSIGN(StateUpdated);
330 };
331
332 class StateUninstalled : public State {
333 public:
334 explicit StateUninstalled(Component* component);
335 ~StateUninstalled() override;
336
337 private:
338 // State overrides.
339 void DoHandle() override;
340
341 DISALLOW_COPY_AND_ASSIGN(StateUninstalled);
342 };
343
Sorin Jianu4ab7c292017-06-15 18:40:21344 class StateRun : public State {
345 public:
346 explicit StateRun(Component* component);
347 ~StateRun() override;
348
349 private:
350 // State overrides.
351 void DoHandle() override;
352
353 void ActionRunComplete(bool succeeded, int error_code, int extra_code1);
354
355 // Runs the action referred by the |action_run_| member of the Component
356 // class.
357 std::unique_ptr<ActionRunner> action_runner_;
358
359 DISALLOW_COPY_AND_ASSIGN(StateRun);
360 };
361
sorin30474f02017-04-27 00:45:48362 // Returns true is the update payload for this component can be downloaded
363 // by a downloader which can do bandwidth throttling on the client side.
364 bool CanDoBackgroundDownload() const;
365
Sorin Jianu039032b2018-10-12 21:48:13366 void AppendEvent(base::Value event);
sorin30474f02017-04-27 00:45:48367
368 // Changes the component state and notifies the caller of the |Handle|
369 // function that the handling of this component state is complete.
370 void ChangeState(std::unique_ptr<State> next_state);
371
372 // Notifies registered observers about changes in the state of the component.
373 void NotifyObservers(Events event) const;
374
Sorin Jianu888ec292018-06-01 15:35:42375 void SetParseResult(const ProtocolParser::Result& result);
376
Sorin Jianu039032b2018-10-12 21:48:13377 // These functions return a specific event. Each data member of the event is
378 // represented as a key-value pair in a dictionary value.
379 base::Value MakeEventUpdateComplete() const;
380 base::Value MakeEventDownloadMetrics(
381 const CrxDownloader::DownloadMetrics& download_metrics) const;
382 base::Value MakeEventUninstalled() const;
383 base::Value MakeEventActionRun(bool succeeded,
384 int error_code,
385 int extra_code1) const;
386
Sorin Jianu9d64af672020-02-05 19:14:34387 std::unique_ptr<CrxInstaller::InstallParams> install_params() const;
388
sorin30474f02017-04-27 00:45:48389 base::ThreadChecker thread_checker_;
390
391 const std::string id_;
Sorin Jianu73900242018-08-17 01:11:53392 base::Optional<CrxComponent> crx_component_;
sorin30474f02017-04-27 00:45:48393
Sorin Jianu4ab7c292017-06-15 18:40:21394 // The status of the updatecheck response.
sorin30474f02017-04-27 00:45:48395 std::string status_;
396
397 // Time when an update check for this CRX has happened.
398 base::TimeTicks last_check_;
399
400 // Time when the update of this CRX has begun.
401 base::TimeTicks update_begin_;
402
403 // A component can be made available for download from several urls.
404 std::vector<GURL> crx_urls_;
405 std::vector<GURL> crx_diffurls_;
406
407 // The cryptographic hash values for the component payload.
408 std::string hash_sha256_;
409 std::string hashdiff_sha256_;
410
411 // The from/to version and fingerprint values.
412 base::Version previous_version_;
413 base::Version next_version_;
414 std::string previous_fp_;
415 std::string next_fp_;
416
Sorin Jianu4ab7c292017-06-15 18:40:21417 // Contains the file name of the payload to run. This member is set by
418 // the update response parser, when the update response includes a run action.
sorin519656c2017-04-28 22:39:34419 std::string action_run_;
420
sorin30474f02017-04-27 00:45:48421 // True if the update check response for this component includes an update.
422 bool is_update_available_ = false;
423
sorin30474f02017-04-27 00:45:48424 // The error reported by the update checker.
425 int update_check_error_ = 0;
426
427 base::FilePath crx_path_;
428
429 // The error information for full and differential updates.
430 // The |error_category| contains a hint about which module in the component
431 // updater generated the error. The |error_code| constains the error and
432 // the |extra_code1| usually contains a system error, but it can contain
433 // any extended information that is relevant to either the category or the
434 // error itself.
Minh X. Nguyena4640cb2018-05-23 21:29:10435 ErrorCategory error_category_ = ErrorCategory::kNone;
sorin30474f02017-04-27 00:45:48436 int error_code_ = 0;
437 int extra_code1_ = 0;
Minh X. Nguyena4640cb2018-05-23 21:29:10438 ErrorCategory diff_error_category_ = ErrorCategory::kNone;
sorin30474f02017-04-27 00:45:48439 int diff_error_code_ = 0;
440 int diff_extra_code1_ = 0;
441
Joshua Pawlickica4f8fa12020-02-25 23:46:06442 // Contains app-specific custom response attributes from the server, sent in
443 // the last update check.
444 std::map<std::string, std::string> custom_attrs_;
445
Sorin Jianu9d64af672020-02-05 19:14:34446 // Contains the optional |run| and |arguments| values in the update response
447 // manifest. This data is provided as an argument to the |Install| call.
448 base::Optional<CrxInstaller::InstallParams> install_params_;
449
Sorin Jianu039032b2018-10-12 21:48:13450 // Contains the events which are therefore serialized in the requests.
451 std::vector<base::Value> events_;
sorin30474f02017-04-27 00:45:48452
453 CallbackHandleComplete callback_handle_complete_;
454 std::unique_ptr<State> state_;
455 const UpdateContext& update_context_;
456
Sorin Jianua8ef73d2017-11-02 16:55:17457 base::OnceClosure update_check_complete_;
sorin30474f02017-04-27 00:45:48458
Sorin Jianu4ab7c292017-06-15 18:40:21459 ComponentState previous_state_ = ComponentState::kLastStatus;
460
Sorin Jianuee5c0db2018-04-12 23:38:47461 // True if this component has reached a final state because all its states
462 // have been handled.
463 bool is_handled_ = false;
464
sorin30474f02017-04-27 00:45:48465 DISALLOW_COPY_AND_ASSIGN(Component);
466};
467
468using IdToComponentPtrMap = std::map<std::string, std::unique_ptr<Component>>;
469
470} // namespace update_client
471
472#endif // COMPONENTS_UPDATE_CLIENT_COMPONENT_H_