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