123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232 |
- // Copyright 2022 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "components/component_updater/installer_policies/url_param_classification_component_installer.h"
- #include "base/bind.h"
- #include "base/callback.h"
- #include "base/files/file_path.h"
- #include "base/files/file_util.h"
- #include "base/logging.h"
- #include "base/memory/ref_counted.h"
- #include "base/metrics/histogram_functions.h"
- #include "base/path_service.h"
- #include "base/task/task_traits.h"
- #include "base/task/thread_pool.h"
- #include "base/version.h"
- #include "components/component_updater/component_updater_paths.h"
- #include "components/url_param_filter/core/features.h"
- #include "components/url_param_filter/core/url_param_classifications_loader.h"
- #include "third_party/abseil-cpp/absl/types/optional.h"
- using component_updater::ComponentUpdateService;
- namespace {
- const base::FilePath::CharType kUrlParamClassificationsFileName[] =
- FILE_PATH_LITERAL("list.pb");
- // The SHA256 of the SubjectPublicKeyInfo used to sign the extension.
- // The extension id is: dnhnnofocefcglhjeigmkhcgfoaipbaa
- const uint8_t kUrlParamClassificationsPublicKeySHA256[32] = {
- 0x3d, 0x7d, 0xde, 0x5e, 0x24, 0x52, 0x6b, 0x79, 0x48, 0x6c, 0xa7,
- 0x26, 0x5e, 0x08, 0xf1, 0x00, 0x82, 0x56, 0x69, 0xb1, 0xca, 0xfc,
- 0x8a, 0x25, 0x50, 0x06, 0x6b, 0x5f, 0xa1, 0xd5, 0xeb, 0x80};
- const char kUrlParamClassificationManifestName[] = "Url Param Classifications";
- // Runs on a thread pool.
- absl::optional<std::string> LoadFileFromDisk(const base::FilePath& pb_path) {
- if (!base::FeatureList::IsEnabled(
- url_param_filter::features::kIncognitoParamFilterEnabled))
- return absl::nullopt;
- VLOG(1) << "Reading Url Param Classifications from file: " << pb_path.value();
- std::string file_contents;
- if (!base::ReadFileToString(pb_path, &file_contents)) {
- // The file won't exist on new installations, so this is not always an
- // error.
- VLOG(1) << "Failed reading from " << pb_path.value();
- return absl::nullopt;
- }
- return file_contents;
- }
- // Writes a metric denoting the |result| of validating a classification list.
- //
- // This method is called in VerifyInstallation which returns false (on an error)
- // or true (if the whole list is valid), so the metrics will be populated at
- // most once per version installed.
- void WriteMetrics(
- component_updater::UrlParamClassificationComponentInstallerPolicy::
- ClassificationListValidationResult result) {
- base::UmaHistogramEnumeration(
- "Navigation.UrlParamFilter.ClassificationListValidationResult", result);
- }
- absl::optional<base::FilePath>& GetConfigPathInstance() {
- // Contains nullopt until registration is complete. Afterward, contains the
- // FilePath for the component file, or an empty FilePath if no component was
- // installed at startup.
- static base::NoDestructor<absl::optional<base::FilePath>> instance;
- return *instance;
- }
- } // namespace
- namespace component_updater {
- UrlParamClassificationComponentInstallerPolicy::
- UrlParamClassificationComponentInstallerPolicy(
- component_updater::OnUrlParamClassificationComponentReady
- on_component_ready)
- : on_component_ready_(on_component_ready) {}
- UrlParamClassificationComponentInstallerPolicy::
- ~UrlParamClassificationComponentInstallerPolicy() = default;
- bool UrlParamClassificationComponentInstallerPolicy::
- SupportsGroupPolicyEnabledComponentUpdates() const {
- return true;
- }
- bool UrlParamClassificationComponentInstallerPolicy::RequiresNetworkEncryption()
- const {
- return false;
- }
- update_client::CrxInstaller::Result
- UrlParamClassificationComponentInstallerPolicy::OnCustomInstall(
- const base::Value& manifest,
- const base::FilePath& install_dir) {
- return update_client::CrxInstaller::Result(0); // Nothing custom here.
- }
- void UrlParamClassificationComponentInstallerPolicy::OnCustomUninstall() {}
- base::FilePath UrlParamClassificationComponentInstallerPolicy::GetInstalledPath(
- const base::FilePath& base) {
- return base.Append(kUrlParamClassificationsFileName);
- }
- void UrlParamClassificationComponentInstallerPolicy::ComponentReady(
- const base::Version& version,
- const base::FilePath& install_dir,
- base::Value manifest) {
- VLOG(1) << "Component ready, version " << version.GetString() << " in "
- << install_dir.value();
- // Given BEST_EFFORT since we don't need to be USER_BLOCKING.
- base::ThreadPool::PostTaskAndReplyWithResult(
- FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
- base::BindOnce(&LoadFileFromDisk, GetInstalledPath(install_dir)),
- base::BindOnce(
- [](OnUrlParamClassificationComponentReady callback,
- const absl::optional<std::string>& maybe_file) {
- if (maybe_file.has_value())
- callback.Run(maybe_file.value());
- },
- on_component_ready_));
- }
- // Called during startup and installation before ComponentReady().
- bool UrlParamClassificationComponentInstallerPolicy::VerifyInstallation(
- const base::Value& manifest,
- const base::FilePath& install_dir) const {
- if (!base::PathExists(GetInstalledPath(install_dir))) {
- WriteMetrics(
- ClassificationListValidationResult::kMissingClassificationsFile);
- return false;
- }
- std::string file_contents;
- if (!base::ReadFileToString(GetInstalledPath(install_dir), &file_contents)) {
- WriteMetrics(
- ClassificationListValidationResult::kReadingClassificationsFileFailed);
- return false;
- }
- url_param_filter::FilterClassifications classification_list;
- if (!classification_list.ParseFromString(file_contents)) {
- WriteMetrics(ClassificationListValidationResult::kParsingToProtoFailed);
- return false;
- }
- for (const url_param_filter::FilterClassification& fc :
- classification_list.classifications()) {
- if (!fc.has_site()) {
- WriteMetrics(
- ClassificationListValidationResult::kClassificationMissingSite);
- return false;
- }
- if (!fc.has_site_role()) {
- WriteMetrics(
- ClassificationListValidationResult::kClassificationMissingSiteRole);
- return false;
- }
- }
- WriteMetrics(ClassificationListValidationResult::kSuccessful);
- return true;
- }
- base::FilePath
- UrlParamClassificationComponentInstallerPolicy::GetRelativeInstallDir() const {
- return base::FilePath(FILE_PATH_LITERAL("UrlParamClassifications"));
- }
- void UrlParamClassificationComponentInstallerPolicy::GetHash(
- std::vector<uint8_t>* hash) const {
- hash->assign(std::begin(kUrlParamClassificationsPublicKeySHA256),
- std::end(kUrlParamClassificationsPublicKeySHA256));
- }
- std::string UrlParamClassificationComponentInstallerPolicy::GetName() const {
- return kUrlParamClassificationManifestName;
- }
- update_client::InstallerAttributes
- UrlParamClassificationComponentInstallerPolicy::GetInstallerAttributes() const {
- return update_client::InstallerAttributes();
- }
- // static
- void UrlParamClassificationComponentInstallerPolicy::WriteComponentForTesting(
- const base::FilePath& install_dir,
- base::StringPiece contents) {
- CHECK(base::WriteFile(GetInstalledPath(install_dir), contents));
- GetConfigPathInstance() = GetInstalledPath(install_dir);
- }
- // static
- void UrlParamClassificationComponentInstallerPolicy::ResetForTesting() {
- GetConfigPathInstance().reset();
- }
- void RegisterUrlParamClassificationComponent(ComponentUpdateService* cus) {
- // Register the component even if feature isn't enabled so that when it is
- // enabled in the future, the component is already installed.
- VLOG(1) << "Registering Url Param Classifications component.";
- auto installer = base::MakeRefCounted<ComponentInstaller>(
- std::make_unique<UrlParamClassificationComponentInstallerPolicy>(
- base::BindRepeating([](std::string raw_classifications) {
- url_param_filter::ClassificationsLoader::GetInstance()
- ->ReadClassifications(raw_classifications);
- })));
- installer->Register(
- cus, base::BindOnce([]() {
- if (GetConfigPathInstance().has_value()) {
- absl::optional<std::string> file_contents =
- LoadFileFromDisk(GetConfigPathInstance().value());
- if (file_contents.has_value()) {
- // Only read classifications after registration if
- // needed for testing.
- url_param_filter::ClassificationsLoader::GetInstance()
- ->ReadClassifications(file_contents.value());
- }
- }
- }));
- }
- } // namespace component_updater
|