blob: 2a75bec6ad8565a65d7c84e08d9fc0276a9a7b4e [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"
19#include "base/threading/thread_checker.h"
20#include "base/time/time.h"
21#include "base/version.h"
sorin30474f02017-04-27 00:45:4822#include "components/update_client/crx_downloader.h"
sorin7cff6e52017-05-17 16:37:2323#include "components/update_client/protocol_parser.h"
sorin30474f02017-04-27 00:45:4824#include "components/update_client/update_client.h"
sorin30474f02017-04-27 00:45:4825#include "url/gurl.h"
26
sorin30474f02017-04-27 00:45:4827
28namespace update_client {
29
Sorin Jianu4ab7c292017-06-15 18:40:2130class ActionRunner;
Sorin Jianub3296162017-12-13 20:26:3231class Configurator;
sorin30474f02017-04-27 00:45:4832struct CrxUpdateItem;
33struct UpdateContext;
34
35// Describes a CRX component managed by the UpdateEngine. Each |Component| is
36// associated with an UpdateContext.
37class Component {
38 public:
39 using Events = UpdateClient::Observer::Events;
40
Sorin Jianua8ef73d2017-11-02 16:55:1741 using CallbackHandleComplete = base::OnceCallback<void()>;
sorin30474f02017-04-27 00:45:4842
43 Component(const UpdateContext& update_context, const std::string& id);
44 ~Component();
45
46 // Handles the current state of the component and makes it transition
Sorin Jianuee5c0db2018-04-12 23:38:4747 // to the next component state before |callback_handle_complete_| is invoked.
48 void Handle(CallbackHandleComplete callback_handle_complete);
sorin30474f02017-04-27 00:45:4849
50 CrxUpdateItem GetCrxUpdateItem() const;
51
52 // Called by the UpdateChecker to set the update response for this component.
sorin7cff6e52017-05-17 16:37:2353 void SetParseResult(const ProtocolParser::Result& result);
sorin30474f02017-04-27 00:45:4854
55 // Sets the uninstall state for this component.
56 void Uninstall(const base::Version& cur_version, int reason);
57
58 // Called by the UpdateEngine when an update check for this component is done.
Sorin Jianua8ef73d2017-11-02 16:55:1759 void UpdateCheckComplete();
sorin30474f02017-04-27 00:45:4860
61 // Returns true if the component has reached a final state and no further
62 // handling and state transitions are possible.
Sorin Jianuee5c0db2018-04-12 23:38:4763 bool IsHandled() const { return is_handled_; }
sorin30474f02017-04-27 00:45:4864
65 // Returns true if an update is available for this component, meaning that
66 // the update server has return a response containing an update.
67 bool IsUpdateAvailable() const { return is_update_available_; }
68
sorin30474f02017-04-27 00:45:4869 base::TimeDelta GetUpdateDuration() const;
70
71 ComponentState state() const { return state_->state(); }
72
73 std::string id() const { return id_; }
74
Sorin Jianu7c22795b2018-04-26 22:16:5275 const CrxComponent* crx_component() const { return crx_component_.get(); }
76 void set_crx_component(std::unique_ptr<CrxComponent> crx_component) {
77 crx_component_ = std::move(crx_component);
sorin30474f02017-04-27 00:45:4878 }
79
80 const base::Version& previous_version() const { return previous_version_; }
81 void set_previous_version(const base::Version& previous_version) {
82 previous_version_ = previous_version;
83 }
84
85 const base::Version& next_version() const { return next_version_; }
86
87 std::string previous_fp() const { return previous_fp_; }
88 void set_previous_fp(const std::string& previous_fp) {
89 previous_fp_ = previous_fp;
90 }
91
92 std::string next_fp() const { return next_fp_; }
93 void set_next_fp(const std::string& next_fp) { next_fp_ = next_fp; }
94
sorin30474f02017-04-27 00:45:4895 void set_update_check_error(int update_check_error) {
Sorin Jianuafcb70dd2018-05-16 20:14:1596 error_category_ = static_cast<int>(ErrorCategory::kUpdateCheck);
97 error_code_ = update_check_error;
98 extra_code1_ = 0;
sorin30474f02017-04-27 00:45:4899 }
100
Sorin Jianub41a592a2018-03-02 16:30:27101 bool is_foreground() const;
sorin30474f02017-04-27 00:45:48102
sorin117334f2017-05-19 02:36:25103 const std::vector<std::string>& events() const { return events_; }
sorin30474f02017-04-27 00:45:48104
105 const std::vector<GURL>& crx_diffurls() const { return crx_diffurls_; }
106
107 bool diff_update_failed() const { return !!diff_error_code_; }
108
109 int error_category() const { return error_category_; }
110 int error_code() const { return error_code_; }
111 int extra_code1() const { return extra_code1_; }
112 int diff_error_category() const { return diff_error_category_; }
113 int diff_error_code() const { return diff_error_code_; }
114 int diff_extra_code1() const { return diff_extra_code1_; }
115
Sorin Jianu4ab7c292017-06-15 18:40:21116 std::string action_run() const { return action_run_; }
117
Sorin Jianub3296162017-12-13 20:26:32118 scoped_refptr<Configurator> config() const;
119
Sorin Jianud69d4372018-02-07 19:44:22120 std::string session_id() const;
121
sorin30474f02017-04-27 00:45:48122 private:
Sorin Jianua8926bf2018-03-09 21:02:53123 friend class MockPingManagerImpl;
sorin30474f02017-04-27 00:45:48124 friend class UpdateCheckerTest;
125
126 FRIEND_TEST_ALL_PREFIXES(PingManagerTest, SendPing);
127 FRIEND_TEST_ALL_PREFIXES(PingManagerTest, RequiresEncryption);
sorin519656c2017-04-28 22:39:34128 FRIEND_TEST_ALL_PREFIXES(UpdateCheckerTest, NoUpdateActionRun);
sorin30474f02017-04-27 00:45:48129 FRIEND_TEST_ALL_PREFIXES(UpdateCheckerTest, UpdateCheckCupError);
130 FRIEND_TEST_ALL_PREFIXES(UpdateCheckerTest, UpdateCheckError);
131 FRIEND_TEST_ALL_PREFIXES(UpdateCheckerTest, UpdateCheckInvalidAp);
132 FRIEND_TEST_ALL_PREFIXES(UpdateCheckerTest,
133 UpdateCheckRequiresEncryptionError);
134 FRIEND_TEST_ALL_PREFIXES(UpdateCheckerTest, UpdateCheckSuccess);
135 FRIEND_TEST_ALL_PREFIXES(UpdateCheckerTest, UpdateCheckUpdateDisabled);
136
137 // Describes an abstraction for implementing the behavior of a component and
138 // the transition from one state to another.
139 class State {
140 public:
141 using CallbackNextState =
Sorin Jianua8ef73d2017-11-02 16:55:17142 base::OnceCallback<void(std::unique_ptr<State> next_state)>;
sorin30474f02017-04-27 00:45:48143
144 State(Component* component, ComponentState state);
145 virtual ~State();
146
147 // Handles the current state and initiates a transition to a new state.
148 // The transition to the new state is non-blocking and it is completed
149 // by the outer component, after the current state is fully handled.
150 void Handle(CallbackNextState callback);
151
152 ComponentState state() const { return state_; }
153
sorin30474f02017-04-27 00:45:48154 protected:
155 // Initiates the transition to the new state.
156 void TransitionState(std::unique_ptr<State> new_state);
157
Sorin Jianuee5c0db2018-04-12 23:38:47158 // Makes the current state a final state where no other state transition
159 // can further occur.
160 void EndState();
161
sorin30474f02017-04-27 00:45:48162 Component& component() { return component_; }
163 const Component& component() const { return component_; }
164
sorin30474f02017-04-27 00:45:48165 base::ThreadChecker thread_checker_;
166
167 const ComponentState state_;
168
169 private:
170 virtual void DoHandle() = 0;
171
172 Component& component_;
Sorin Jianuee5c0db2018-04-12 23:38:47173 CallbackNextState callback_next_state_;
sorin30474f02017-04-27 00:45:48174 };
175
176 class StateNew : public State {
177 public:
178 explicit StateNew(Component* component);
179 ~StateNew() override;
180
181 private:
182 // State overrides.
183 void DoHandle() override;
184
185 DISALLOW_COPY_AND_ASSIGN(StateNew);
186 };
187
188 class StateChecking : public State {
189 public:
190 explicit StateChecking(Component* component);
191 ~StateChecking() override;
192
193 private:
194 // State overrides.
195 void DoHandle() override;
196
197 void UpdateCheckComplete();
198
199 DISALLOW_COPY_AND_ASSIGN(StateChecking);
200 };
201
202 class StateUpdateError : public State {
203 public:
204 explicit StateUpdateError(Component* component);
205 ~StateUpdateError() override;
206
207 private:
208 // State overrides.
209 void DoHandle() override;
210
211 DISALLOW_COPY_AND_ASSIGN(StateUpdateError);
212 };
213
214 class StateCanUpdate : public State {
215 public:
216 explicit StateCanUpdate(Component* component);
217 ~StateCanUpdate() override;
218
219 private:
220 // State overrides.
221 void DoHandle() override;
222 bool CanTryDiffUpdate() const;
223
224 DISALLOW_COPY_AND_ASSIGN(StateCanUpdate);
225 };
226
227 class StateUpToDate : public State {
228 public:
229 explicit StateUpToDate(Component* component);
230 ~StateUpToDate() override;
231
232 private:
233 // State overrides.
234 void DoHandle() override;
235
236 DISALLOW_COPY_AND_ASSIGN(StateUpToDate);
237 };
238
239 class StateDownloadingDiff : public State {
240 public:
241 explicit StateDownloadingDiff(Component* component);
242 ~StateDownloadingDiff() override;
243
244 private:
245 // State overrides.
246 void DoHandle() override;
247
248 // Called when progress is being made downloading a CRX. The progress may
249 // not monotonically increase due to how the CRX downloader switches between
250 // different downloaders and fallback urls.
251 void DownloadProgress(const std::string& id,
252 const CrxDownloader::Result& download_result);
253
254 void DownloadComplete(const std::string& id,
255 const CrxDownloader::Result& download_result);
256
257 // Downloads updates for one CRX id only.
258 std::unique_ptr<CrxDownloader> crx_downloader_;
259
260 DISALLOW_COPY_AND_ASSIGN(StateDownloadingDiff);
261 };
262
263 class StateDownloading : public State {
264 public:
265 explicit StateDownloading(Component* component);
266 ~StateDownloading() override;
267
268 private:
269 // State overrides.
270 void DoHandle() override;
271
272 // Called when progress is being made downloading a CRX. The progress may
273 // not monotonically increase due to how the CRX downloader switches between
274 // different downloaders and fallback urls.
275 void DownloadProgress(const std::string& id,
276 const CrxDownloader::Result& download_result);
277
278 void DownloadComplete(const std::string& id,
279 const CrxDownloader::Result& download_result);
280
281 // Downloads updates for one CRX id only.
282 std::unique_ptr<CrxDownloader> crx_downloader_;
283
284 DISALLOW_COPY_AND_ASSIGN(StateDownloading);
285 };
286
287 class StateUpdatingDiff : public State {
288 public:
289 explicit StateUpdatingDiff(Component* component);
290 ~StateUpdatingDiff() override;
291
292 private:
293 // State overrides.
294 void DoHandle() override;
295
296 void InstallComplete(int error_category, int error_code, int extra_code1);
297
298 DISALLOW_COPY_AND_ASSIGN(StateUpdatingDiff);
299 };
300
301 class StateUpdating : public State {
302 public:
303 explicit StateUpdating(Component* component);
304 ~StateUpdating() override;
305
306 private:
307 // State overrides.
308 void DoHandle() override;
309
310 void InstallComplete(int error_category, int error_code, int extra_code1);
311
sorin30474f02017-04-27 00:45:48312 DISALLOW_COPY_AND_ASSIGN(StateUpdating);
313 };
314
315 class StateUpdated : public State {
316 public:
317 explicit StateUpdated(Component* component);
318 ~StateUpdated() override;
319
320 private:
321 // State overrides.
322 void DoHandle() override;
323
324 DISALLOW_COPY_AND_ASSIGN(StateUpdated);
325 };
326
327 class StateUninstalled : public State {
328 public:
329 explicit StateUninstalled(Component* component);
330 ~StateUninstalled() override;
331
332 private:
333 // State overrides.
334 void DoHandle() override;
335
336 DISALLOW_COPY_AND_ASSIGN(StateUninstalled);
337 };
338
Sorin Jianu4ab7c292017-06-15 18:40:21339 class StateRun : public State {
340 public:
341 explicit StateRun(Component* component);
342 ~StateRun() override;
343
344 private:
345 // State overrides.
346 void DoHandle() override;
347
348 void ActionRunComplete(bool succeeded, int error_code, int extra_code1);
349
350 // Runs the action referred by the |action_run_| member of the Component
351 // class.
352 std::unique_ptr<ActionRunner> action_runner_;
353
354 DISALLOW_COPY_AND_ASSIGN(StateRun);
355 };
356
sorin30474f02017-04-27 00:45:48357 // Returns true is the update payload for this component can be downloaded
358 // by a downloader which can do bandwidth throttling on the client side.
359 bool CanDoBackgroundDownload() const;
360
sorin117334f2017-05-19 02:36:25361 void AppendEvent(const std::string& event);
sorin30474f02017-04-27 00:45:48362
363 // Changes the component state and notifies the caller of the |Handle|
364 // function that the handling of this component state is complete.
365 void ChangeState(std::unique_ptr<State> next_state);
366
367 // Notifies registered observers about changes in the state of the component.
368 void NotifyObservers(Events event) const;
369
370 base::ThreadChecker thread_checker_;
371
372 const std::string id_;
Sorin Jianu7c22795b2018-04-26 22:16:52373 std::unique_ptr<CrxComponent> crx_component_;
sorin30474f02017-04-27 00:45:48374
Sorin Jianu4ab7c292017-06-15 18:40:21375 // The status of the updatecheck response.
sorin30474f02017-04-27 00:45:48376 std::string status_;
377
378 // Time when an update check for this CRX has happened.
379 base::TimeTicks last_check_;
380
381 // Time when the update of this CRX has begun.
382 base::TimeTicks update_begin_;
383
384 // A component can be made available for download from several urls.
385 std::vector<GURL> crx_urls_;
386 std::vector<GURL> crx_diffurls_;
387
388 // The cryptographic hash values for the component payload.
389 std::string hash_sha256_;
390 std::string hashdiff_sha256_;
391
392 // The from/to version and fingerprint values.
393 base::Version previous_version_;
394 base::Version next_version_;
395 std::string previous_fp_;
396 std::string next_fp_;
397
Sorin Jianu4ab7c292017-06-15 18:40:21398 // Contains the file name of the payload to run. This member is set by
399 // the update response parser, when the update response includes a run action.
sorin519656c2017-04-28 22:39:34400 std::string action_run_;
401
sorin30474f02017-04-27 00:45:48402 // True if the update check response for this component includes an update.
403 bool is_update_available_ = false;
404
sorin30474f02017-04-27 00:45:48405 // The error reported by the update checker.
406 int update_check_error_ = 0;
407
408 base::FilePath crx_path_;
409
410 // The error information for full and differential updates.
411 // The |error_category| contains a hint about which module in the component
412 // updater generated the error. The |error_code| constains the error and
413 // the |extra_code1| usually contains a system error, but it can contain
414 // any extended information that is relevant to either the category or the
415 // error itself.
416 int error_category_ = 0;
417 int error_code_ = 0;
418 int extra_code1_ = 0;
419 int diff_error_category_ = 0;
420 int diff_error_code_ = 0;
421 int diff_extra_code1_ = 0;
422
sorin117334f2017-05-19 02:36:25423 // Contains the events which are serialized in the pings.
424 std::vector<std::string> events_;
sorin30474f02017-04-27 00:45:48425
426 CallbackHandleComplete callback_handle_complete_;
427 std::unique_ptr<State> state_;
428 const UpdateContext& update_context_;
429
Sorin Jianua8ef73d2017-11-02 16:55:17430 base::OnceClosure update_check_complete_;
sorin30474f02017-04-27 00:45:48431
Sorin Jianu4ab7c292017-06-15 18:40:21432 ComponentState previous_state_ = ComponentState::kLastStatus;
433
Sorin Jianuee5c0db2018-04-12 23:38:47434 // True if this component has reached a final state because all its states
435 // have been handled.
436 bool is_handled_ = false;
437
sorin30474f02017-04-27 00:45:48438 DISALLOW_COPY_AND_ASSIGN(Component);
439};
440
441using IdToComponentPtrMap = std::map<std::string, std::unique_ptr<Component>>;
442
443} // namespace update_client
444
445#endif // COMPONENTS_UPDATE_CLIENT_COMPONENT_H_