Chromium Code Reviews| Index: components/update_client/component.h |
| diff --git a/components/update_client/component.h b/components/update_client/component.h |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..6e3ef0deb86e452709f9d77bceb601a31c768fa0 |
| --- /dev/null |
| +++ b/components/update_client/component.h |
| @@ -0,0 +1,437 @@ |
| +// Copyright 2017 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#ifndef COMPONENTS_UPDATE_CLIENT_COMPONENT_H_ |
| +#define COMPONENTS_UPDATE_CLIENT_COMPONENT_H_ |
| + |
| +#include <map> |
| +#include <memory> |
| +#include <string> |
| +#include <utility> |
| +#include <vector> |
| + |
| +#include "base/callback.h" |
| +#include "base/files/file_path.h" |
| +#include "base/gtest_prod_util.h" |
| +#include "base/macros.h" |
| +#include "base/memory/ref_counted.h" |
| +#include "base/threading/thread_checker.h" |
| +#include "base/time/time.h" |
| +#include "base/version.h" |
| +#include "components/update_client/component_unpacker.h" |
| +#include "components/update_client/crx_downloader.h" |
| +#include "components/update_client/update_client.h" |
| +#include "components/update_client/update_response.h" |
| +#include "url/gurl.h" |
| + |
| +namespace base { |
| +class SingleThreadTaskRunner; |
| +} |
| + |
| +namespace update_client { |
| + |
| +struct CrxUpdateItem; |
| +struct UpdateContext; |
| + |
| +// Describes a CRX component managed by the UpdateEngine. A |Component| can |
| +// only exists if it is associated with an UpdateContext. |
|
waffles
2017/04/24 18:57:22
exists → exist
or "Each |Component| is associated
Sorin Jianu
2017/04/24 23:26:45
Done.
|
| +class Component { |
| + public: |
| + using Events = UpdateClient::Observer::Events; |
| + |
| + using CallbackHandleComplete = base::Callback<void()>; |
| + |
| + Component(const UpdateContext& update_context, const std::string& id); |
| + ~Component(); |
| + |
| + // Handles the current state of the component and makes it transition |
| + // to the next component state before |callback| is invoked. |
| + void Handle(CallbackHandleComplete callback); |
| + |
| + CrxUpdateItem GetCrxUpdateItem() const; |
| + |
| + // Called by the UpdateChecker to set the update response for this component. |
| + void SetParseResult(const UpdateResponse::Result& result); |
| + |
| + // Sets the uninstall state for this component. |
| + void Uninstall(const base::Version& cur_version, int reason); |
| + |
| + // Called by the UpdateEngine when an update check for this component is done. |
| + void UpdateCheckComplete() const; |
| + |
| + // Returns true if the component has reached a final state and no further |
| + // handling and state transitions are possible. |
| + bool IsHandled() const { return state_->IsFinal(); } |
| + |
| + // Returns true if an update is available for this component, meaning that |
| + // the update server has return a response containing an update. |
| + bool IsUpdateAvailable() const { return is_update_available_; } |
| + |
| + // Returns true if a ping must be sent back to the server. As a general rule, |
| + // a ping is sent only for server responses containing instructions to update. |
| + bool CanPing() const { |
| + return IsUpdateAvailable() || state() == ComponentState::kUninstalled; |
| + } |
| + |
| + base::TimeDelta GetUpdateDuration() const; |
| + |
| + ComponentState state() const { return state_->state(); } |
| + |
| + std::string id() const { return id_; } |
| + |
| + const CrxComponent& crx_component() const { return crx_component_; } |
| + void set_crx_component(const CrxComponent& crx_component) { |
| + crx_component_ = crx_component; |
| + } |
| + |
| + const base::Version& previous_version() const { return previous_version_; } |
| + void set_previous_version(const base::Version& previous_version) { |
| + previous_version_ = previous_version; |
| + } |
| + |
| + const base::Version& next_version() const { return next_version_; } |
| + |
| + std::string previous_fp() const { return previous_fp_; } |
| + void set_previous_fp(const std::string& previous_fp) { |
| + previous_fp_ = previous_fp; |
| + } |
| + |
| + std::string next_fp() const { return next_fp_; } |
| + void set_next_fp(const std::string& next_fp) { next_fp_ = next_fp; } |
| + |
| + int update_check_error() const { return update_check_error_; } |
| + void set_update_check_error(int update_check_error) { |
| + update_check_error_ = update_check_error; |
| + } |
| + |
| + // Returns the time when processing of an update for this component has |
| + // begun, once the update has been discovered. Returns a null TimeTicks object |
| + // if the handling of an update has not happened. |
| + // base::TimeTicks update_begin() const { return update_begin_; } |
| + |
| + bool on_demand() const { return on_demand_; } |
| + void set_on_demand(bool on_demand) { on_demand_ = on_demand; } |
| + |
| + const std::vector<CrxDownloader::DownloadMetrics>& download_metrics() const { |
| + return download_metrics_; |
| + } |
| + |
| + const std::vector<GURL>& crx_diffurls() const { return crx_diffurls_; } |
| + |
| + bool diff_update_failed() const { return !!diff_error_code_; } |
| + |
| + int error_category() const { return error_category_; } |
| + int error_code() const { return error_code_; } |
| + int extra_code1() const { return extra_code1_; } |
| + int diff_error_category() const { return diff_error_category_; } |
| + int diff_error_code() const { return diff_error_code_; } |
| + int diff_extra_code1() const { return diff_extra_code1_; } |
| + |
| + private: |
| + friend class FakePingManagerImpl; |
| + friend class UpdateCheckerTest; |
| + |
| + FRIEND_TEST_ALL_PREFIXES(PingManagerTest, SendPing); |
| + FRIEND_TEST_ALL_PREFIXES(PingManagerTest, RequiresEncryption); |
| + FRIEND_TEST_ALL_PREFIXES(UpdateCheckerTest, UpdateCheckCupError); |
| + FRIEND_TEST_ALL_PREFIXES(UpdateCheckerTest, UpdateCheckError); |
| + FRIEND_TEST_ALL_PREFIXES(UpdateCheckerTest, UpdateCheckInvalidAp); |
| + FRIEND_TEST_ALL_PREFIXES(UpdateCheckerTest, |
| + UpdateCheckRequiresEncryptionError); |
| + FRIEND_TEST_ALL_PREFIXES(UpdateCheckerTest, UpdateCheckSuccess); |
| + FRIEND_TEST_ALL_PREFIXES(UpdateCheckerTest, UpdateCheckUpdateDisabled); |
| + |
| + // Describes an abstraction for implementing the behavior of a component and |
| + // the transition from one state to another. |
| + class State { |
| + public: |
| + using CallbackNextState = |
| + base::Callback<void(std::unique_ptr<State> next_state)>; |
| + |
| + State(Component* component, ComponentState state); |
|
waffles
2017/04/24 18:57:22
Should this be protected?
Sorin Jianu
2017/04/24 23:26:45
It seems ok to be public. The inner base class is
|
| + virtual ~State(); |
| + |
| + // Handles the current state and initiates a transition to a new state. |
| + // The transition to the new state is non-blocking and it is completed |
| + // by the outer component, after the current state is fully handled. |
| + void Handle(CallbackNextState callback); |
| + |
| + ComponentState state() const { return state_; } |
| + |
| + bool IsFinal() const { return is_final_; } |
| + |
| + protected: |
| + // Initiates the transition to the new state. |
| + void TransitionState(std::unique_ptr<State> new_state); |
| + |
| + Component& component() { return component_; } |
| + const Component& component() const { return component_; } |
| + |
| + CallbackNextState callback() const { return callback_; } |
| + |
| + base::ThreadChecker thread_checker_; |
| + |
| + const ComponentState state_; |
| + |
| + private: |
| + virtual void DoHandle() = 0; |
| + |
| + Component& component_; |
| + CallbackNextState callback_; |
| + |
| + bool is_final_ = false; |
| + }; |
| + |
| + class StateNew : public State { |
| + public: |
| + explicit StateNew(Component* component); |
| + ~StateNew() override; |
| + |
| + private: |
| + // State overrides. |
| + void DoHandle() override; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(StateNew); |
| + }; |
| + |
| + class StateChecking : public State { |
| + public: |
| + explicit StateChecking(Component* component); |
| + ~StateChecking() override; |
| + |
| + private: |
| + // State overrides. |
| + void DoHandle() override; |
| + |
| + void UpdateCheckComplete(); |
| + |
| + DISALLOW_COPY_AND_ASSIGN(StateChecking); |
| + }; |
| + |
| + class StateUpdateError : public State { |
| + public: |
| + explicit StateUpdateError(Component* component); |
| + ~StateUpdateError() override; |
| + |
| + private: |
| + // State overrides. |
| + void DoHandle() override; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(StateUpdateError); |
| + }; |
| + |
| + class StateCanUpdate : public State { |
| + public: |
| + explicit StateCanUpdate(Component* component); |
| + ~StateCanUpdate() override; |
| + |
| + private: |
| + // State overrides. |
| + void DoHandle() override; |
| + bool CanTryDiffUpdate() const; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(StateCanUpdate); |
| + }; |
| + |
| + class StateUpToDate : public State { |
| + public: |
| + explicit StateUpToDate(Component* component); |
| + ~StateUpToDate() override; |
| + |
| + private: |
| + // State overrides. |
| + void DoHandle() override; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(StateUpToDate); |
| + }; |
| + |
| + class StateDownloadingDiff : public State { |
| + public: |
| + explicit StateDownloadingDiff(Component* component); |
| + ~StateDownloadingDiff() override; |
| + |
| + private: |
| + // State overrides. |
| + void DoHandle() override; |
| + |
| + // Called when progress is being made downloading a CRX. The progress may |
| + // not monotonically increase due to how the CRX downloader switches between |
| + // different downloaders and fallback urls. |
| + void DownloadProgress(const std::string& id, |
| + const CrxDownloader::Result& download_result); |
| + |
| + void DownloadComplete(const std::string& id, |
| + const CrxDownloader::Result& download_result); |
| + |
| + // Downloads updates for one CRX id only. |
| + std::unique_ptr<CrxDownloader> crx_downloader_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(StateDownloadingDiff); |
| + }; |
| + |
| + class StateDownloading : public State { |
| + public: |
| + explicit StateDownloading(Component* component); |
| + ~StateDownloading() override; |
| + |
| + private: |
| + // State overrides. |
| + void DoHandle() override; |
| + |
| + // Called when progress is being made downloading a CRX. The progress may |
| + // not monotonically increase due to how the CRX downloader switches between |
| + // different downloaders and fallback urls. |
| + void DownloadProgress(const std::string& id, |
| + const CrxDownloader::Result& download_result); |
| + |
| + void DownloadComplete(const std::string& id, |
| + const CrxDownloader::Result& download_result); |
| + |
| + // Downloads updates for one CRX id only. |
| + std::unique_ptr<CrxDownloader> crx_downloader_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(StateDownloading); |
| + }; |
| + |
| + class StateUpdatingDiff : public State { |
| + public: |
| + explicit StateUpdatingDiff(Component* component); |
| + ~StateUpdatingDiff() override; |
| + |
| + private: |
| + // State overrides. |
| + void DoHandle() override; |
| + |
| + void InstallComplete(int error_category, int error_code, int extra_code1); |
| + |
| + DISALLOW_COPY_AND_ASSIGN(StateUpdatingDiff); |
| + }; |
| + |
| + class StateUpdating : public State { |
| + public: |
| + explicit StateUpdating(Component* component); |
| + ~StateUpdating() override; |
| + |
| + private: |
| + // State overrides. |
| + void DoHandle() override; |
| + |
| + void InstallComplete(int error_category, int error_code, int extra_code1); |
| + |
| + // Posts replies back to the main thread. |
| + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_; |
| + |
| + // Unpacks one CRX. |
| + scoped_refptr<ComponentUnpacker> unpacker_; |
| + |
| + base::FilePath unpack_path_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(StateUpdating); |
| + }; |
| + |
| + class StateUpdated : public State { |
| + public: |
| + explicit StateUpdated(Component* component); |
| + ~StateUpdated() override; |
| + |
| + private: |
| + // State overrides. |
| + void DoHandle() override; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(StateUpdated); |
| + }; |
| + |
| + class StateUninstalled : public State { |
| + public: |
| + explicit StateUninstalled(Component* component); |
| + ~StateUninstalled() override; |
| + |
| + private: |
| + // State overrides. |
| + void DoHandle() override; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(StateUninstalled); |
| + }; |
| + |
| + // Returns true is the update payload for this component can be downloaded |
| + // by a downloader which can do bandwidth throttling on the client side. |
| + bool CanDoBackgroundDownload() const; |
| + |
| + void AppendDownloadMetrics( |
| + const std::vector<CrxDownloader::DownloadMetrics>& download_metrics); |
| + |
| + // Changes the component state and notifies the caller of the |Handle| |
| + // function that the handling of this component state is complete. |
| + void ChangeState(std::unique_ptr<State> next_state); |
| + |
| + // Notifies registered observers about changes in the state of the component. |
| + void NotifyObservers(Events event) const; |
| + |
| + base::ThreadChecker thread_checker_; |
| + |
| + const std::string id_; |
| + CrxComponent crx_component_; |
| + |
| + std::string status_; |
| + |
| + // Time when an update check for this CRX has happened. |
| + base::TimeTicks last_check_; |
| + |
| + // Time when the update of this CRX has begun. |
| + base::TimeTicks update_begin_; |
| + |
| + // A component can be made available for download from several urls. |
| + std::vector<GURL> crx_urls_; |
| + std::vector<GURL> crx_diffurls_; |
| + |
| + // The cryptographic hash values for the component payload. |
| + std::string hash_sha256_; |
| + std::string hashdiff_sha256_; |
| + |
| + // The from/to version and fingerprint values. |
| + base::Version previous_version_; |
| + base::Version next_version_; |
| + std::string previous_fp_; |
| + std::string next_fp_; |
| + |
| + // True if the update check response for this component includes an update. |
| + bool is_update_available_ = false; |
| + |
| + // True if the current update check cycle is on-demand. |
| + bool on_demand_ = false; |
| + |
| + // The error reported by the update checker. |
| + int update_check_error_ = 0; |
| + |
| + base::FilePath crx_path_; |
| + |
| + // The error information for full and differential updates. |
| + // The |error_category| contains a hint about which module in the component |
| + // updater generated the error. The |error_code| constains the error and |
| + // the |extra_code1| usually contains a system error, but it can contain |
| + // any extended information that is relevant to either the category or the |
| + // error itself. |
| + int error_category_ = 0; |
| + int error_code_ = 0; |
| + int extra_code1_ = 0; |
| + int diff_error_category_ = 0; |
| + int diff_error_code_ = 0; |
| + int diff_extra_code1_ = 0; |
| + |
| + std::vector<CrxDownloader::DownloadMetrics> download_metrics_; |
| + |
| + CallbackHandleComplete callback_handle_complete_; |
| + std::unique_ptr<State> state_; |
| + const UpdateContext& update_context_; |
| + |
| + base::Closure update_check_complete_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(Component); |
| +}; |
| + |
| +using IdToComponentPtrMap = std::map<std::string, std::unique_ptr<Component>>; |
| + |
| +} // namespace update_client |
| + |
| +#endif // COMPONENTS_UPDATE_CLIENT_COMPONENT_H_ |