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_
|