1 // Copyright 2014 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef COMPONENTS_COMPONENT_UPDATER_COMPONENT_INSTALLER_H_
6 #define COMPONENTS_COMPONENT_UPDATER_COMPONENT_INSTALLER_H_
14 #include "base/files/file_path.h"
15 #include "base/functional/callback_forward.h"
16 #include "base/gtest_prod_util.h"
17 #include "base/memory/ref_counted.h"
18 #include "base/sequence_checker.h"
19 #include "base/task/task_traits.h"
20 #include "base/values.h"
21 #include "base/version.h"
22 #include "components/update_client/persisted_data.h"
23 #include "components/update_client/update_client.h"
24 #include "third_party/abseil-cpp/absl/types/optional.h"
27 class SequencedTaskRunner;
30 namespace component_updater {
32 // Version "0.0.0.0" corresponds to no installed version. By the server's
33 // conventions, we represent it as a dotted quad.
34 extern const char kNullVersion[];
36 struct ComponentRegistration;
37 class ComponentUpdateService;
39 using RegisterCallback = base::OnceCallback<bool(const ComponentRegistration&)>;
41 // Components should use a ComponentInstaller by defining a class that
42 // implements the members of ComponentInstallerPolicy, and then registering a
43 // ComponentInstaller that has been constructed with an instance of that
45 class ComponentInstallerPolicy {
47 virtual ~ComponentInstallerPolicy();
49 // Verifies that a working installation resides within the directory specified
50 // by |install_dir|. |install_dir| is of the form <base directory>/<version>.
51 // |manifest| should have been read from the manifest file in
52 // |install_dir|. Called only from a thread belonging to a blocking thread
53 // pool. The implementation of this function must be efficient since the
54 // function can be called when Chrome starts.
55 virtual bool VerifyInstallation(const base::Value::Dict& manifest,
56 const base::FilePath& install_dir) const = 0;
58 // Returns true if the component supports a group policy to enable updates.
59 // Called once during component registration from the UI thread.
60 virtual bool SupportsGroupPolicyEnabledComponentUpdates() const = 0;
62 // Returns true if the network communication related to this component
64 virtual bool RequiresNetworkEncryption() const = 0;
66 // OnCustomInstall is called during the installation process. Components that
67 // require custom installation operations should implement them here. Returns
68 // a failure result if a custom operation failed, and
69 // update_client::InstallError::NONE otherwise. Called only from a thread
70 // belonging to a blocking thread pool.
71 virtual update_client::CrxInstaller::Result OnCustomInstall(
72 const base::Value::Dict& manifest,
73 const base::FilePath& install_dir) = 0;
75 // OnCustomUninstall is called during the unregister (uninstall) process.
76 // Components that require custom uninstallation operations should implement
78 // Called only from a thread belonging to a blocking thread pool.
79 virtual void OnCustomUninstall() = 0;
81 // ComponentReady is called in two cases:
82 // 1) After an installation is successfully completed.
83 // 2) During component registration if the component is already installed.
84 // In both cases the install is verified before this is called. This method
85 // is guaranteed to be called before any observers of the component are
86 // notified of a successful install, and is meant to support follow-on work
87 // such as updating paths elsewhere in Chrome. Called on the UI thread.
88 // |version| is the version of the component.
89 // |install_dir| is the path to the install directory for this version.
90 // |manifest| is the manifest for this version of the component.
91 virtual void ComponentReady(const base::Version& version,
92 const base::FilePath& install_dir,
93 base::Value::Dict manifest) = 0;
95 // Returns a relative path that will be appended to the component updater
96 // root directories to find the data for this particular component.
97 virtual base::FilePath GetRelativeInstallDir() const = 0;
99 // Returns the component's SHA2 hash as raw bytes.
100 virtual void GetHash(std::vector<uint8_t>* hash) const = 0;
102 // Returns the human-readable name of the component.
103 virtual std::string GetName() const = 0;
105 // Returns a container of name-value pairs representing arbitrary,
106 // installer-defined metadata.
107 // The installer metadata may be used in the update checks for this component.
108 // A compatible server may use these attributes to negotiate special update
109 // rules when issuing an update response.
110 // Valid values for the name part of an attribute match
111 // ^[-_a-zA-Z0-9]{1,256}$ and valid values the value part of an attribute
112 // match ^[-.,;+_=$a-zA-Z0-9]{0,256}$ .
113 virtual update_client::InstallerAttributes GetInstallerAttributes() const = 0;
116 // Defines the installer for Chrome components. The behavior of this class is
117 // controlled by an instance of ComponentInstallerPolicy, at construction time.
118 class ComponentInstaller final : public update_client::CrxInstaller {
121 std::unique_ptr<ComponentInstallerPolicy> installer_policy,
122 scoped_refptr<update_client::ActionHandler> action_handler = nullptr);
124 ComponentInstaller(const ComponentInstaller&) = delete;
125 ComponentInstaller& operator=(const ComponentInstaller&) = delete;
127 // Registers the component for update checks and installs.
128 // |cus| provides the registration logic.
129 // The passed |callback| will be called once the initial check for installed
130 // versions is done and the component has been registered.
131 // Registration tasks will be done with a priority of |task_priority|. Some
132 // components may affect user-visible features, hence a default of
135 ComponentUpdateService* cus,
136 base::OnceClosure callback,
137 base::TaskPriority task_priority = base::TaskPriority::USER_VISIBLE);
139 // Registers the component for update checks and installs.
140 // |register_callback| is called to do the registration.
141 // |callback| is called when registration finishes.
142 // Registration tasks will be done with a priority of |task_priority|. Some
143 // components may affect user-visible features, hence a default of
146 RegisterCallback register_callback,
147 base::OnceClosure callback,
148 base::TaskPriority task_priority = base::TaskPriority::USER_VISIBLE,
149 const base::Version& registered_version = base::Version(kNullVersion));
151 // Overrides from update_client::CrxInstaller.
152 void OnUpdateError(int error) override;
154 void Install(const base::FilePath& unpack_path,
155 const std::string& public_key,
156 std::unique_ptr<InstallParams> install_params,
157 ProgressCallback progress_callback,
158 Callback callback) override;
160 bool GetInstalledFile(const std::string& file,
161 base::FilePath* installed_file) override;
162 // Only user-level component installations can be uninstalled.
163 bool Uninstall() override;
166 struct RegistrationInfo : base::RefCountedThreadSafe<RegistrationInfo> {
169 RegistrationInfo(const RegistrationInfo&) = delete;
170 RegistrationInfo& operator=(const RegistrationInfo&) = delete;
172 base::FilePath install_dir;
173 base::Version version;
174 std::string fingerprint;
175 absl::optional<base::Value::Dict> manifest;
178 friend class base::RefCountedThreadSafe<RegistrationInfo>;
183 ~ComponentInstaller() override;
185 // If there is a installation of the component set up alongside Chrome's
186 // files (as opposed to in the user data directory), sets current_* to the
187 // values associated with that installation and returns true; otherwise,
189 bool FindPreinstallation(const base::FilePath& root,
190 scoped_refptr<RegistrationInfo> registration_info);
191 update_client::CrxInstaller::Result InstallHelper(
192 const base::FilePath& unpack_path,
193 base::Value::Dict* manifest,
194 base::Version* version,
195 base::FilePath* install_path);
196 void StartRegistration(const base::Version& registered_version,
197 scoped_refptr<RegistrationInfo> registration_info);
198 void FinishRegistration(scoped_refptr<RegistrationInfo> registration_info,
199 RegisterCallback register_callback,
200 base::OnceClosure callback);
201 absl::optional<base::Value::Dict> GetValidInstallationManifest(
202 const base::FilePath& path);
203 absl::optional<base::Version> SelectComponentVersion(
204 const base::Version& registered_version,
205 const base::FilePath& base_dir,
206 scoped_refptr<RegistrationInfo> registration_info);
208 void DeleteUnselectedComponentVersions(
209 const base::FilePath& base_dir,
210 const absl::optional<base::Version>& selected_version);
211 absl::optional<base::FilePath> GetComponentDirectory();
212 void ComponentReady(base::Value::Dict manifest);
213 void UninstallOnTaskRunner();
215 SEQUENCE_CHECKER(sequence_checker_);
217 base::FilePath current_install_dir_;
218 base::Version current_version_;
219 std::string current_fingerprint_;
221 std::unique_ptr<ComponentInstallerPolicy> installer_policy_;
222 scoped_refptr<update_client::ActionHandler> action_handler_;
223 scoped_refptr<base::SequencedTaskRunner> task_runner_;
225 // Posts responses back to the main thread.
226 scoped_refptr<base::SequencedTaskRunner> main_task_runner_;
228 FRIEND_TEST_ALL_PREFIXES(ComponentInstallerTest, SelectComponentVersion);
231 } // namespace component_updater
233 #endif // COMPONENTS_COMPONENT_UPDATER_COMPONENT_INSTALLER_H_