blob: d24ccb3c9cb28577354e9b94bc35b986515fae4b [file] [log] [blame]
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/component_updater/privacy_sandbox_attestations_component_installer.h"
#include <cstdint>
#include <memory>
#include <utility>
#include <vector>
#include "base/feature_list.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/functional/callback.h"
#include "base/logging.h"
#include "base/memory/scoped_refptr.h"
#include "base/path_service.h"
#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
#include "base/time/time.h"
#include "base/values.h"
#include "base/version.h"
#include "chrome/common/chrome_paths.h"
#include "components/component_updater/component_installer.h"
#include "components/privacy_sandbox/privacy_sandbox_attestations/privacy_sandbox_attestations.h"
#include "components/privacy_sandbox/privacy_sandbox_features.h"
#include "components/startup_metric_utils/browser/startup_metric_utils.h"
#include "components/update_client/update_client.h"
namespace {
constexpr base::FilePath::CharType kPrivacySandboxAttestationsFileName[] =
FILE_PATH_LITERAL("privacy-sandbox-attestations.dat");
constexpr base::FilePath::CharType
kPrivacySandboxAttestationsRelativeInstallDir[] =
FILE_PATH_LITERAL("PrivacySandboxAttestationsPreloaded");
// The SHA256 of the SubjectPublicKeyInfo used to sign the extension.
// The extension id is: niikhdgajlphfehepabhhblakbdgeefj
constexpr uint8_t kPrivacySandboxAttestationsPublicKeySHA256[32] = {
0xd8, 0x8a, 0x73, 0x60, 0x9b, 0xf7, 0x54, 0x74, 0xf0, 0x17, 0x71,
0xb0, 0xa1, 0x36, 0x44, 0x59, 0xf6, 0x22, 0x38, 0xa8, 0x7c, 0xc9,
0x7b, 0x7a, 0x43, 0x2c, 0x72, 0xee, 0x04, 0x01, 0xae, 0xc0};
const char kPrivacySandboxAttestationsManifestName[] =
"Privacy Sandbox Attestations";
} // namespace
namespace component_updater {
PrivacySandboxAttestationsComponentInstallerPolicy::
PrivacySandboxAttestationsComponentInstallerPolicy(
AttestationsReadyRepeatingCallback on_attestations_ready)
: on_attestations_ready_(std::move(on_attestations_ready)) {}
PrivacySandboxAttestationsComponentInstallerPolicy::
~PrivacySandboxAttestationsComponentInstallerPolicy() = default;
bool PrivacySandboxAttestationsComponentInstallerPolicy::VerifyInstallation(
const base::Value::Dict& manifest,
const base::FilePath& install_dir) const {
return base::PathExists(GetInstalledFilePath(install_dir));
}
bool PrivacySandboxAttestationsComponentInstallerPolicy::
SupportsGroupPolicyEnabledComponentUpdates() const {
return true;
}
bool PrivacySandboxAttestationsComponentInstallerPolicy::
RequiresNetworkEncryption() const {
// Privacy sandbox attestations are identical for all users.
return false;
}
update_client::CrxInstaller::Result
PrivacySandboxAttestationsComponentInstallerPolicy::OnCustomInstall(
const base::Value::Dict& manifest,
const base::FilePath& install_dir) {
// No custom install for privacy sandbox attestations.
return update_client::CrxInstaller::Result(0);
}
void PrivacySandboxAttestationsComponentInstallerPolicy::OnCustomUninstall() {}
void PrivacySandboxAttestationsComponentInstallerPolicy::ComponentReady(
const base::Version& version,
const base::FilePath& install_dir,
base::Value::Dict manifest) {
if (!base::FeatureList::IsEnabled(
privacy_sandbox::kEnforcePrivacySandboxAttestations)) {
// Privacy Sandbox Enrollment is not enforced if the feature is disabled.
return;
}
if (on_attestations_ready_.is_null()) {
return;
}
if (install_dir.empty() || !version.IsValid()) {
return;
}
// Record the time taken for the downloaded attestations file to be detected.
startup_metric_utils::GetBrowser().RecordPrivacySandboxAttestationsFirstReady(
base::TimeTicks::Now());
VLOG(1) << "Privacy Sandbox Attestations Component ready, version "
<< version.GetString() << " in " << install_dir.value();
on_attestations_ready_.Run(
std::move(version),
/*installed_file_path=*/
PrivacySandboxAttestationsComponentInstallerPolicy::GetInstalledFilePath(
install_dir),
/*is_pre_installed=*/manifest.FindBool("pre_installed").value_or(false));
}
base::FilePath
PrivacySandboxAttestationsComponentInstallerPolicy::GetRelativeInstallDir()
const {
return base::FilePath(kPrivacySandboxAttestationsRelativeInstallDir);
}
void PrivacySandboxAttestationsComponentInstallerPolicy::GetHash(
std::vector<uint8_t>* hash) const {
hash->assign(std::begin(kPrivacySandboxAttestationsPublicKeySHA256),
std::end(kPrivacySandboxAttestationsPublicKeySHA256));
}
std::string PrivacySandboxAttestationsComponentInstallerPolicy::GetName()
const {
return kPrivacySandboxAttestationsManifestName;
}
update_client::InstallerAttributes
PrivacySandboxAttestationsComponentInstallerPolicy::GetInstallerAttributes()
const {
return update_client::InstallerAttributes();
}
void PrivacySandboxAttestationsComponentInstallerPolicy::
ComponentReadyForTesting(const base::Version& version,
const base::FilePath& install_dir,
base::Value::Dict manifest) {
ComponentReady(version, install_dir, std::move(manifest));
}
// static
base::FilePath
PrivacySandboxAttestationsComponentInstallerPolicy::GetInstalledFilePath(
const base::FilePath& base) {
return base.Append(kPrivacySandboxAttestationsFileName);
}
// static
base::FilePath
PrivacySandboxAttestationsComponentInstallerPolicy::GetInstalledDirectory(
const base::FilePath& base) {
return base.Append(kPrivacySandboxAttestationsRelativeInstallDir);
}
void RegisterPrivacySandboxAttestationsComponent(ComponentUpdateService* cus) {
if (!base::FeatureList::IsEnabled(
privacy_sandbox::kEnforcePrivacySandboxAttestations)) {
// Privacy sandbox enrollment is not enforced if the feature is disabled.
// Any existing version of this component is deleted.
base::FilePath user_path;
if (base::PathService::Get(chrome::DIR_USER_DATA, &user_path)) {
base::ThreadPool::PostTask(
FROM_HERE, {base::TaskPriority::LOWEST, base::MayBlock()},
base::GetDeletePathRecursivelyCallback(
user_path.Append(kPrivacySandboxAttestationsRelativeInstallDir)));
}
return;
}
VLOG(1) << "Registering Privacy Sandbox Attestations component";
auto policy =
std::make_unique<PrivacySandboxAttestationsComponentInstallerPolicy>(
/*on_attestations_ready=*/base::BindRepeating(
[](base::Version version, base::FilePath install_dir,
bool is_pre_installed) {
VLOG(1) << "Received privacy sandbox attestations file";
privacy_sandbox::PrivacySandboxAttestations::GetInstance()
->LoadAttestations(std::move(version),
std::move(install_dir),
is_pre_installed);
}));
base::MakeRefCounted<ComponentInstaller>(std::move(policy),
/*action_handler=*/nullptr,
base::TaskPriority::USER_BLOCKING)
->Register(cus, base::BindOnce([]() {
privacy_sandbox::PrivacySandboxAttestations::GetInstance()
->OnAttestationsFileCheckComplete();
}));
}
} // namespace component_updater