chromium/chrome/browser/win/conflicts/module_list_filter.cc

// Copyright 2018 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/win/conflicts/module_list_filter.h"

#include <string>
#include <string_view>

#include "base/check.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/hash/sha1.h"
#include "base/i18n/case_conversion.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/win/conflicts/module_info.h"

namespace {

bool MatchesModuleGroup(const chrome::conflicts::ModuleGroup& module_group,
                        std::string_view module_basename_hash,
                        std::string_view module_code_id_hash) {
  // Now look at each module in the group in detail.
  for (const auto& module : module_group.modules()) {
    // A valid entry contains one of the basename and the code id.
    if (!module.has_basename_hash() && !module.has_code_id_hash())
      continue;

    // Skip this entry if it doesn't match the basename of the module.
    if (module.has_basename_hash() &&
        module.basename_hash() != module_basename_hash) {
      continue;
    }

    // Or the code id.
    if (module.has_code_id_hash() &&
        module.code_id_hash() != module_code_id_hash) {
      continue;
    }

    return true;
  }

  return false;
}

}  // namespace

ModuleListFilter::ModuleListFilter() = default;

ModuleListFilter::~ModuleListFilter() = default;

bool ModuleListFilter::Initialize(const base::FilePath& module_list_path) {
  DCHECK(!initialized_);

  std::string contents;
  initialized_ = base::ReadFileToString(module_list_path, &contents) &&
                 module_list_.ParseFromString(contents);

  return initialized_;
}

bool ModuleListFilter::IsAllowlisted(
    std::string_view module_basename_hash,
    std::string_view module_code_id_hash) const {
  DCHECK(initialized_);

  for (const auto& module_group : module_list_.allowlist().module_groups()) {
    if (MatchesModuleGroup(module_group, module_basename_hash,
                           module_code_id_hash)) {
      return true;
    }
  }

  return false;
}

bool ModuleListFilter::IsAllowlisted(const ModuleInfoKey& module_key,
                                     const ModuleInfoData& module_data) const {
  // Precompute the hash of the basename and of the code id.
  const std::string module_basename_hash =
      base::SHA1HashString(base::UTF16ToUTF8(
          base::i18n::ToLower(module_data.inspection_result->basename)));
  const std::string module_code_id_hash =
      base::SHA1HashString(GenerateCodeId(module_key));

  return IsAllowlisted(module_basename_hash, module_code_id_hash);
}

std::unique_ptr<chrome::conflicts::BlocklistAction>
ModuleListFilter::IsBlocklisted(const ModuleInfoKey& module_key,
                                const ModuleInfoData& module_data) const {
  DCHECK(initialized_);

  // Precompute the hash of the basename and of the code id.
  const std::string module_basename_hash =
      base::SHA1HashString(base::UTF16ToUTF8(
          base::i18n::ToLower(module_data.inspection_result->basename)));
  const std::string module_code_id_hash =
      base::SHA1HashString(GenerateCodeId(module_key));

  for (const auto& blocklist_module_group :
       module_list_.blocklist().module_groups()) {
    if (MatchesModuleGroup(blocklist_module_group.modules(),
                           module_basename_hash, module_code_id_hash)) {
      return std::make_unique<chrome::conflicts::BlocklistAction>(
          blocklist_module_group.action());
    }
  }

  return nullptr;
}