chromium/android_webview/browser/enterprise_authentication_app_link_policy_handler.cc

// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "android_webview/browser/enterprise_authentication_app_link_policy_handler.h"

#include <memory>

#include "base/strings/string_util.h"
#include "components/policy/core/common/policy_pref_names.h"
#include "components/policy/policy_constants.h"
#include "components/strings/grit/components_strings.h"
#include "url/gurl.h"

namespace policy {
EnterpriseAuthenticationAppLinkPolicyHandler::
    EnterpriseAuthenticationAppLinkPolicyHandler(const char* policy_name,
                                                 const char* pref_path)
    : TypeCheckingPolicyHandler(policy_name, base::Value::Type::LIST),
      pref_path_(pref_path) {}

EnterpriseAuthenticationAppLinkPolicyHandler::
    ~EnterpriseAuthenticationAppLinkPolicyHandler() = default;

bool EnterpriseAuthenticationAppLinkPolicyHandler::CheckPolicySettings(
    const PolicyMap& policies,
    PolicyErrorMap* errors) {
  if (!TypeCheckingPolicyHandler::CheckPolicySettings(policies, errors))
    return false;

  const base::Value* value =
      policies.GetValue(policy_name(), base::Value::Type::LIST);
  if (!value) {
    return true;
  }

  const base::Value::List& policy_list = value->GetList();
  if (policy_list.empty()) {
    return true;
  }

  // Filters more than |url_util::kMaxFiltersPerPolicy| are ignored, add a
  // warning message.
  if (policy_list.size() > policy::kMaxUrlFiltersPerPolicy) {
    errors->AddError(policy_name(),
                     IDS_POLICY_URL_ALLOW_BLOCK_LIST_MAX_FILTERS_LIMIT_WARNING,
                     base::NumberToString(policy::kMaxUrlFiltersPerPolicy));
  }

  std::vector<std::string> invalid_policies;
  for (const auto& entry : policy_list) {
    const std::string* url = entry.GetDict().FindString("url");
    if (!url) {
      invalid_policies.push_back(
          "Invalid policy: Required key 'url' does not exists");
    } else if (!ValidatePolicyEntry(url)) {
      invalid_policies.push_back("Invalid url: " + *url);
    }
  }

  if (!invalid_policies.empty()) {
    errors->AddError(policy_name(), IDS_POLICY_PROTO_PARSING_ERROR,
                     base::JoinString(invalid_policies, ","));
  }

  return invalid_policies.size() < policy_list.size();
}

void EnterpriseAuthenticationAppLinkPolicyHandler::ApplyPolicySettings(
    const PolicyMap& policies,
    PrefValueMap* prefs) {
  const base::Value* value =
      policies.GetValue(policy_name(), base::Value::Type::LIST);
  if (!value)
    return;

  base::Value::List filtered_values;
  for (const auto& entry : value->GetList()) {
    const std::string* url = entry.GetDict().FindString("url");
    if (ValidatePolicyEntry(url))
      filtered_values.Append(*url);
  }
  if (filtered_values.size() > policy::kMaxUrlFiltersPerPolicy) {
    filtered_values.erase(
        filtered_values.begin() + policy::kMaxUrlFiltersPerPolicy,
        filtered_values.end());
  }

  prefs->SetValue(pref_path_, base::Value(std::move(filtered_values)));
}

// Validates that policy follows official pattern
// https://www.chromium.org/administrators/url-blocklist-filter-format
bool EnterpriseAuthenticationAppLinkPolicyHandler::ValidatePolicyEntry(
    const std::string* policy) {
  url_matcher::util::FilterComponents components;
  return policy && url_matcher::util::FilterToComponents(
                       *policy, &components.scheme, &components.host,
                       &components.match_subdomains, &components.port,
                       &components.path, &components.query);
}

}  // namespace policy