File: cros_component_installer_chromeos.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (301 lines) | stat: -rw-r--r-- 12,462 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_COMPONENT_UPDATER_CROS_COMPONENT_INSTALLER_CHROMEOS_H_
#define CHROME_BROWSER_COMPONENT_UPDATER_CROS_COMPONENT_INSTALLER_CHROMEOS_H_

#include <memory>
#include <optional>
#include <string>
#include <vector>

#include "base/containers/flat_map.h"
#include "base/gtest_prod_util.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "components/component_updater/ash/component_manager_ash.h"
#include "components/component_updater/component_installer.h"
#include "components/component_updater/component_updater_service.h"
#include "components/update_client/update_client.h"

namespace component_updater {

// The name of the directory under DIR_COMPONENT_USER that cros component
// installers puts all of the installed components.
extern const char kComponentsRootPath[];

class ComponentUpdateService;
class MetadataTable;
class CrOSComponentInstaller;

// Describes all metadata needed to dynamically install ChromeOS components.
struct ComponentConfig {
  // This is a client-only identifier for the component.
  const char* name;
  // ComponentInstallerPolicy to use.
  enum class PolicyType {
    kEnvVersion,       // Checks env_version, see below.
    kDemoApp,          // Adds demo-mode-specific install attributes
    kGrowthCampaigns,  // Adds growth campaigns install attributes
  };
  PolicyType policy_type;
  // This is used for ABI compatibility checks. It is compared against the
  // 'min_env_version' key in the component's manifest.json file. It uses
  // standard major.minor compat rules, where ABI is compatible if and only if
  // major is matching. The client will send this string to the omaha server,
  // which will filter for a compatible update. Likewise, the client will
  // avoid registering a component if there is an ABI mismatch between the
  // already downloaded component and the expected major version. Must be
  // non-empty for PolicyType::kEnvVersion.
  const char* env_version;
  // This is the app-id of the component, converted from [a-p] hex to [0-f] hex.
  const char* sha2hash;
};

// Base class for all Chrome OS components.
class CrOSComponentInstallerPolicy : public ComponentInstallerPolicy {
 public:
  CrOSComponentInstallerPolicy(
      const ComponentConfig& config,
      CrOSComponentInstaller* cros_component_installer);

  CrOSComponentInstallerPolicy(const CrOSComponentInstallerPolicy&) = delete;
  CrOSComponentInstallerPolicy& operator=(const CrOSComponentInstallerPolicy&) =
      delete;

  ~CrOSComponentInstallerPolicy() override;

  // ComponentInstallerPolicy:
  bool SupportsGroupPolicyEnabledComponentUpdates() const override;
  bool RequiresNetworkEncryption() const override;
  update_client::CrxInstaller::Result OnCustomInstall(
      const base::Value::Dict& manifest,
      const base::FilePath& install_dir) override;
  void OnCustomUninstall() override;
  bool VerifyInstallation(const base::Value::Dict& manifest,
                          const base::FilePath& install_dir) const override;
  base::FilePath GetRelativeInstallDir() const override;
  void GetHash(std::vector<uint8_t>* hash) const override;
  std::string GetName() const override;
  bool AllowUpdates() const override;

 protected:
  const raw_ptr<CrOSComponentInstaller, DanglingUntriaged>
      cros_component_installer_;

 private:
  const std::string name_;
  std::vector<uint8_t> sha2_hash_;
};

// An installer policy that does ABI compatibility checks based on
// ComponentConfig::env_version, see above.
class EnvVersionInstallerPolicy : public CrOSComponentInstallerPolicy {
 public:
  EnvVersionInstallerPolicy(const ComponentConfig& config,
                            CrOSComponentInstaller* cros_component_installer);
  EnvVersionInstallerPolicy(const EnvVersionInstallerPolicy&) = delete;
  EnvVersionInstallerPolicy& operator=(const EnvVersionInstallerPolicy&) =
      delete;
  ~EnvVersionInstallerPolicy() override;

  // ComponentInstallerPolicy:
  void ComponentReady(const base::Version& version,
                      const base::FilePath& path,
                      base::Value::Dict manifest) override;
  update_client::InstallerAttributes GetInstallerAttributes() const override;

 private:
  FRIEND_TEST_ALL_PREFIXES(CrOSComponentInstallerTest, IsCompatibleOrNot);

  static bool IsCompatible(const std::string& env_version_str,
                           const std::string& min_env_version_str);

  const std::string env_version_;
};

// An installer policy for the ChromeOS Demo Mode app, which includes special
// system-sourced installer attributes in the request to receive customized
// app versions
class DemoAppInstallerPolicy : public CrOSComponentInstallerPolicy {
 public:
  DemoAppInstallerPolicy(const ComponentConfig& config,
                         CrOSComponentInstaller* cros_component_installer);
  DemoAppInstallerPolicy(const DemoAppInstallerPolicy&) = delete;
  DemoAppInstallerPolicy& operator=(const DemoAppInstallerPolicy&) = delete;
  ~DemoAppInstallerPolicy() override;

  // ComponentInstallerPolicy:
  void ComponentReady(const base::Version& version,
                      const base::FilePath& path,
                      base::Value::Dict manifest) override;
  update_client::InstallerAttributes GetInstallerAttributes() const override;
};

// An installer policy for the ChromeOS growth campaigns, which includes special
// system-sourced installer attributes in the request to receive customized
// campaigns versions.
class GrowthCampaignsInstallerPolicy : public CrOSComponentInstallerPolicy {
 public:
  GrowthCampaignsInstallerPolicy(
      const ComponentConfig& config,
      CrOSComponentInstaller* cros_component_installer);
  GrowthCampaignsInstallerPolicy(const GrowthCampaignsInstallerPolicy&) =
      delete;
  GrowthCampaignsInstallerPolicy& operator=(
      const GrowthCampaignsInstallerPolicy&) = delete;
  ~GrowthCampaignsInstallerPolicy() override;

  // ComponentInstallerPolicy:
  void ComponentReady(const base::Version& version,
                      const base::FilePath& path,
                      base::Value::Dict manifest) override;
  update_client::InstallerAttributes GetInstallerAttributes() const override;
};

// This class contains functions used to register and install a component.
class CrOSComponentInstaller : public ComponentManagerAsh {
 public:
  CrOSComponentInstaller(std::unique_ptr<MetadataTable> metadata_table,
                         ComponentUpdateService* component_updater);

  CrOSComponentInstaller(const CrOSComponentInstaller&) = delete;
  CrOSComponentInstaller& operator=(const CrOSComponentInstaller&) = delete;

  // ComponentManagerAsh:
  void SetDelegate(Delegate* delegate) override;
  void Load(const std::string& name,
            MountPolicy mount_policy,
            UpdatePolicy update_policy,
            LoadCallback load_callback) override;
  bool Unload(const std::string& name) override;
  void GetVersion(const std::string& name,
                  base::OnceCallback<void(const base::Version&)>
                      version_callback) const override;
  void RegisterCompatiblePath(const std::string& name,
                              CompatibleComponentInfo info) override;
  void RegisterInstalled() override;

  void UnregisterCompatiblePath(const std::string& name) override;
  base::FilePath GetCompatiblePath(const std::string& name) const override;
  bool IsRegisteredMayBlock(const std::string& name) override;

  // Called when a component is installed/updated.
  // Broadcasts a D-Bus signal for a successful component installation.
  void EmitInstalledSignal(const std::string& component);

  // The load cache contains three pieces of information:
  //   (1) For a given component, whether the load request was successful, a
  //   failure, or in-progress.
  //   (2) If the load request was successful, the file path to the loaded
  //   image.
  //   (3) If the load request is in progress, the callbacks to invoke after the
  //   load request finishes.
  struct LoadInfo {
    LoadInfo();
    ~LoadInfo();
    // If null, then the request is pending.
    std::optional<bool> success;
    // Only populated on success.
    base::FilePath path;
    // Only populated if request is pending. Includes all subsequent callbacks
    // after the first.
    std::vector<LoadCallback> callbacks;
  };

  // Removes the load cache entry for `component_name`. Currently this is done
  // to avoid dispatching loads for old component versions. This can occur when
  // the old version has loaded successfully and is now in the load cache.
  void RemoveLoadCacheEntry(const std::string& component_name);

  // Test-only method for introspection.
  std::map<std::string, LoadInfo>& GetLoadCacheForTesting();

 protected:
  ~CrOSComponentInstaller() override;

 private:
  FRIEND_TEST_ALL_PREFIXES(CrOSComponentInstallerTest, RegisterComponent);
  FRIEND_TEST_ALL_PREFIXES(CrOSComponentInstallerTest,
                           BPPPCompatibleCrOSComponent);
  FRIEND_TEST_ALL_PREFIXES(CrOSComponentInstallerTest, CompatibilityOK);
  FRIEND_TEST_ALL_PREFIXES(CrOSComponentInstallerTest,
                           CompatibilityMissingManifest);
  FRIEND_TEST_ALL_PREFIXES(CrOSComponentInstallerTest, IsCompatibleOrNot);
  FRIEND_TEST_ALL_PREFIXES(CrOSComponentInstallerTest, CompatibleCrOSComponent);

  // Registers a component with a dedicated ComponentUpdateService instance.
  void Register(const ComponentConfig& config,
                base::OnceClosure register_callback);

  // Installs a component with a dedicated ComponentUpdateService instance.
  void Install(const std::string& name,
               UpdatePolicy update_policy,
               MountPolicy mount_policy,
               LoadCallback load_callback);

  // Calls OnDemandUpdate to install the component right after being registered.
  // |id| is the component id generated from its sha2 hash.
  void StartInstall(const std::string& name,
                    const std::string& id,
                    UpdatePolicy update_policy,
                    update_client::Callback install_callback);

  // Calls LoadInternal to load the installed component.
  void FinishInstall(const std::string& name,
                     MountPolicy mount_policy,
                     UpdatePolicy update_policy,
                     LoadCallback load_callback,
                     update_client::Error error);

  // Internal function to load a component.
  void LoadInternal(const std::string& name, LoadCallback load_callback);

  // Calls load_callback and pass in the parameter |result| (component mount
  // point).
  void FinishLoad(LoadCallback load_callback,
                  const std::string& name,
                  std::optional<base::FilePath> result);

  // Calls `version_callback` and pass in the parameter `result` (component
  // version).
  void FinishGetVersion(
      base::OnceCallback<void(const base::Version&)> version_callback,
      std::optional<std::string> result) const;

  // Registers component |configs| to be updated.
  void RegisterN(const std::vector<ComponentConfig>& configs);

  // Checks if the current installed component is compatible given a component
  // |name|.
  bool IsCompatible(const std::string& name) const;

  // Posts a task with the response information for |callback|.
  void DispatchLoadCallback(LoadCallback callback,
                            base::FilePath path,
                            bool success);
  // Repeatedly calls DispatchLoadCallback with failure parameters.
  void DispatchFailedLoads(std::vector<LoadCallback> callbacks);

  // Maps from a compatible component name to its info.
  base::flat_map<std::string, CompatibleComponentInfo> compatible_components_;

  // A weak pointer to a Delegate for emitting D-Bus signal.
  raw_ptr<Delegate> delegate_ = nullptr;

  // Table storing metadata (installs, usage, etc.).
  std::unique_ptr<MetadataTable> metadata_table_;

  // The load cache stores ongoing load requests, as well as the finished
  // results.
  std::map<std::string, LoadInfo> load_cache_;

  const raw_ptr<ComponentUpdateService> component_updater_;

  base::WeakPtrFactory<CrOSComponentInstaller> weak_factory_{this};
};

}  // namespace component_updater

#endif  // CHROME_BROWSER_COMPONENT_UPDATER_CROS_COMPONENT_INSTALLER_CHROMEOS_H_