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

#include "components/omnibox/browser/base_search_provider.h"

#include <stddef.h>
#include <stdint.h>

#include <algorithm>
#include <memory>
#include <vector>

#include "base/feature_list.h"
#include "base/functional/bind.h"
#include "base/i18n/case_conversion.h"
#include "base/memory/scoped_refptr.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "components/omnibox/browser/actions/omnibox_action_in_suggest.h"
#include "components/omnibox/browser/actions/omnibox_answer_action.h"
#include "components/omnibox/browser/aim_eligibility_service.h"
#include "components/omnibox/browser/autocomplete_provider_client.h"
#include "components/omnibox/browser/autocomplete_provider_listener.h"
#include "components/omnibox/browser/omnibox_field_trial.h"
#include "components/omnibox/browser/omnibox_prefs.h"
#include "components/omnibox/browser/page_classification_functions.h"
#include "components/omnibox/browser/remote_suggestions_service.h"
#include "components/omnibox/browser/search_scoring_signals_annotator.h"
#include "components/omnibox/browser/suggestion_answer.h"
#include "components/omnibox/common/omnibox_feature_configs.h"
#include "components/omnibox/common/omnibox_features.h"
#include "components/search/search.h"
#include "components/search_engines/template_url.h"
#include "components/search_engines/template_url_service.h"
#include "components/variations/net/variations_http_headers.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/public/cpp/simple_url_loader.h"
#include "services/network/public/mojom/url_response_head.mojom.h"
#include "third_party/metrics_proto/omnibox_input_type.pb.h"
#include "third_party/omnibox_proto/navigational_intent.pb.h"
#include "third_party/omnibox_proto/rich_answer_template.pb.h"
#include "url/gurl.h"
#include "url/origin.h"

namespace {
constexpr bool is_android = !!BUILDFLAG(IS_ANDROID);
constexpr bool is_ios = !!BUILDFLAG(IS_IOS);

bool MatchTypeAndContentsAreEqual(const AutocompleteMatch& lhs,
                                  const AutocompleteMatch& rhs) {
  return lhs.contents == rhs.contents && lhs.type == rhs.type;
}

std::u16string GetMatchContentsForOnDeviceTailSuggestion(
    const std::u16string& input_text,
    const std::u16string& sanitized_suggestion) {
  std::u16string sanitized_input;

  base::TrimWhitespace(input_text, base::TRIM_TRAILING, &sanitized_input);
  sanitized_input = AutocompleteMatch::SanitizeString(sanitized_input);

  if (!base::StartsWith(sanitized_suggestion, sanitized_input,
                        base::CompareCase::SENSITIVE)) {
    return sanitized_suggestion;
  }

  // If there is no space inside the suggestion, show the entire suggestion in
  // UI. Otherwise replace the completed prefix of the suggestion with tail UI
  // symbols e.g. "...".
  // Examples (input/suggestion -> result):
  // 1. [googl]/[google] -> [google]
  // 2. [google]/[google map] -> [google map]
  // 3. [google ma]/[google map login] -> [...map login]
  // 4. [google map ]/[google map login] -> [...map login]
  size_t suggestion_last_space_index =
      sanitized_suggestion.find_last_of(base::kWhitespaceUTF16);
  size_t input_last_space_index =
      sanitized_input.find_last_of(base::kWhitespaceUTF16);
  if (suggestion_last_space_index == std::u16string::npos ||
      input_last_space_index == std::u16string::npos) {
    return sanitized_suggestion;
  }
  size_t start_index = input_last_space_index + 1;

  return sanitized_suggestion.substr(start_index);
}

}  // namespace

using OEP = metrics::OmniboxEventProto;

BaseSearchProvider::BaseSearchProvider(AutocompleteProvider::Type type,
                                       AutocompleteProviderClient* client)
    : AutocompleteProvider(type), client_(client) {}

// static
bool BaseSearchProvider::ShouldPrefetch(const AutocompleteMatch& match) {
  // TODO (manukh): `GetAdditionalInfoForDebugging()` shouldn't be used for
  //   non-debugging purposes.
  return match.GetAdditionalInfoForDebugging(kShouldPrefetchKey) == kTrue;
}

// static
bool BaseSearchProvider::ShouldPrerender(const AutocompleteMatch& match) {
  // TODO (manukh): `GetAdditionalInfoForDebugging()` shouldn't be used for
  //   non-debugging purposes.
  return match.GetAdditionalInfoForDebugging(kShouldPrerenderKey) == kTrue;
}

// static
AutocompleteMatch BaseSearchProvider::CreateSearchSuggestion(
    AutocompleteProvider* autocomplete_provider,
    const AutocompleteInput& input,
    const bool in_keyword_mode,
    const SearchSuggestionParser::SuggestResult& suggestion,
    const TemplateURL* template_url,
    const SearchTermsData& search_terms_data,
    int accepted_suggestion,
    bool append_extra_query_params_from_command_line) {
  AutocompleteMatch match(autocomplete_provider, suggestion.relevance(), false,
                          suggestion.type());

  if (!template_url)
    return match;
  match.keyword = template_url->keyword();
  // If SuggestTemplateInfo is available, use it. Otherwise, continue
  // populating information from EntityInfo.
  const auto& suggest_template_info = suggestion.suggest_template_info();
  if (suggest_template_info) {
    match.suggest_template = suggest_template_info;
    if (suggest_template_info->has_image()) {
      match.image_dominant_color =
          suggest_template_info->image().dominant_color();
      match.image_url = GURL(suggest_template_info->image().url());
    }
  } else {
    match.image_dominant_color = suggestion.entity_info().dominant_color();
    match.image_url = GURL(suggestion.entity_info().image_url());
  }
  match.entity_id = suggestion.entity_info().entity_id();
  match.website_uri = suggestion.entity_info().website_uri();
  match.contents = suggestion.match_contents();
  match.contents_class = suggestion.match_contents_class();
  if (OmniboxFieldTrial::kAnswerActionsShowRichCard.Get() &&
      suggestion.answer_template() &&
      suggestion.answer_template()->enhancements().enhancements().size() > 0) {
    match.suggestion_group_id = omnibox::GROUP_MOBILE_RICH_ANSWER;
  } else {
    match.suggestion_group_id = suggestion.suggestion_group_id();
  }
  match.answer_template = suggestion.answer_template();
  match.answer_type = suggestion.answer_type();
  match.suggest_type = suggestion.suggest_type();
  for (const int subtype : suggestion.subtypes()) {
    match.subtypes.insert(SuggestSubtypeForNumber(subtype));
  }
  if (suggestion.type() == AutocompleteMatchType::SEARCH_SUGGEST_TAIL) {
    match.RecordAdditionalInfo(kACMatchPropertySuggestionText,
                               suggestion.suggestion());
    match.RecordAdditionalInfo(kACMatchPropertyContentsPrefix,
                               suggestion.match_contents_prefix());
    match.RecordAdditionalInfo(
        kACMatchPropertyContentsStartIndex,
        static_cast<int>(suggestion.suggestion().length() -
                         match.contents.length()));
  }

  if (!suggestion.annotation().empty()) {
    match.description = suggestion.annotation();
    // Descriptions should always have dimmed text.
    AutocompleteMatch::AddLastClassificationIfNecessary(
        &match.description_class, 0, ACMatchClassification::DIM);
  }

  const std::u16string input_text = input.IsZeroSuggest() ? u"" : input.text();
  const std::u16string input_lower = base::i18n::ToLower(input_text);
  // suggestion.match_contents() should have already been collapsed.
  match.allowed_to_be_default_match =
      (!in_keyword_mode || suggestion.from_keyword()) &&
      (base::CollapseWhitespace(input_lower, false) ==
       base::i18n::ToLower(suggestion.match_contents()));

  if (suggestion.from_keyword())
    match.from_keyword = true;

  // We only allow inlinable navsuggestions that were received before the
  // last keystroke because we don't want asynchronous inline autocompletions.
  if (!input.prevent_inline_autocomplete() &&
      !suggestion.received_after_last_keystroke() &&
      (!in_keyword_mode || suggestion.from_keyword()) &&
      !input.IsZeroSuggest() &&
      base::StartsWith(base::i18n::ToLower(suggestion.suggestion()),
                       input_lower, base::CompareCase::SENSITIVE)) {
    match.inline_autocompletion =
        suggestion.suggestion().substr(input_text.length());
    match.allowed_to_be_default_match = true;
  }

  const TemplateURLRef& search_url = template_url->url_ref();
  DCHECK(search_url.SupportsReplacement(search_terms_data));
  std::u16string query(suggestion.suggestion());
  std::u16string original_query(input_text);
  if (suggestion.type() == AutocompleteMatchType::CALCULATOR) {
    // Use query text, rather than the calculator answer suggestion, to search.
    query = original_query;
    original_query.clear();
  }
  match.fill_into_edit = GetFillIntoEdit(suggestion, template_url);
  match.search_terms_args =
      std::make_unique<TemplateURLRef::SearchTermsArgs>(query);
  match.search_terms_args->request_source = input.request_source();
  match.search_terms_args->original_query = original_query;
  match.search_terms_args->accepted_suggestion = accepted_suggestion;
  if (suggest_template_info) {
    match.search_terms_args->additional_query_params =
        CreateQueryParamStringFromMap(
            suggest_template_info->default_search_parameters());
  } else {
    match.search_terms_args->additional_query_params =
        suggestion.entity_info().suggest_search_parameters();
  }
  match.search_terms_args->append_extra_query_params_from_command_line =
      append_extra_query_params_from_command_line;
  // Must be set for deduplication and navigation. AutocompleteController will
  // ultimately overwrite this with the searchbox stats before navigation.
  match.destination_url = GURL(search_url.ReplaceSearchTerms(
      *match.search_terms_args, search_terms_data));

  // Search results don't look like URLs.
  match.transition = suggestion.from_keyword() ? ui::PAGE_TRANSITION_KEYWORD
                                               : ui::PAGE_TRANSITION_GENERATED;

  bool is_google = search::TemplateURLIsGoogle(template_url, search_terms_data);
  // Attach Actions in Suggest to the newly created match on Android if Google
  // is the default search engine.
  if ((is_android || is_ios) && is_google) {
    if (suggest_template_info &&
        suggest_template_info->action_suggestions_size() > 0) {
      for (const omnibox::SuggestTemplateInfo_TemplateAction& action :
           suggest_template_info->action_suggestions()) {
        match.actions.emplace_back(CreateActionInSuggest(
            action, search_url, *match.search_terms_args, search_terms_data));
      }
    } else {
      // TODO(crbug.com/417745802): Remove once actions are migrated from
      // EntityInfo to SuggestTemplateInfo.
      for (const omnibox::ActionInfo& action_info :
           suggestion.entity_info().action_suggestions()) {
        omnibox::SuggestTemplateInfo::TemplateAction template_action;
        template_action.set_action_uri(action_info.action_uri());
        template_action.set_logs_action_type(action_info.logs_action_type());
        template_action.set_action_type(
            static_cast<omnibox::SuggestTemplateInfo_TemplateAction_ActionType>(
                action_info.action_type()));
        *template_action.mutable_search_parameters() =
            action_info.search_parameters();
        match.actions.emplace_back(
            CreateActionInSuggest(template_action, search_url,
                                  *match.search_terms_args, search_terms_data));
      }
    }
  }

  if (is_android && is_google && suggestion.answer_template()) {
    std::ranges::transform(
        suggestion.answer_template()->enhancements().enhancements(),
        std::back_inserter(match.actions),
        [&](const omnibox::SuggestionEnhancement& enhancement) {
          return CreateAnswerAction(enhancement, *match.search_terms_args,
                                    suggestion.answer_type());
        });
  }

  match.navigational_intent = suggestion.navigational_intent();

  return match;
}

scoped_refptr<OmniboxAction> BaseSearchProvider::CreateActionInSuggest(
    omnibox::SuggestTemplateInfo::TemplateAction template_action,
    const TemplateURLRef& search_url,
    const TemplateURLRef::SearchTermsArgs& original_search_terms_args,
    const SearchTermsData& search_terms_data) {
  std::optional<TemplateURLRef::SearchTermsArgs> action_search_terms_args;
  // If the Action's URL is empty, but the Action supplies additional search
  // parameters, compute new URL based on the base URL (that is specific to
  // the entire suggestion).
  if (template_action.action_uri().empty() &&
      !template_action.search_parameters().empty()) {
    action_search_terms_args = original_search_terms_args;
    action_search_terms_args->additional_query_params =
        CreateQueryParamStringFromMap(template_action.search_parameters());
  }

  return base::MakeRefCounted<OmniboxActionInSuggest>(
      std::move(template_action), std::move(action_search_terms_args));
}

// static
scoped_refptr<OmniboxAction> BaseSearchProvider::CreateAnswerAction(
    omnibox::SuggestionEnhancement enhancement,
    TemplateURLRef::SearchTermsArgs search_terms_args,
    omnibox::AnswerType answer_type) {
  // Define actions destination URL.
  search_terms_args.additional_query_params =
      CreateQueryParamStringFromMap(enhancement.query_cgi_params());
  search_terms_args.search_terms = base::UTF8ToUTF16(enhancement.query());

  return base::MakeRefCounted<OmniboxAnswerAction>(
      std::move(enhancement), search_terms_args, answer_type);
}

// static
std::string BaseSearchProvider::CreateQueryParamStringFromMap(
    const google::protobuf::Map<std::string, std::string>& query_param_map) {
  std::string query_params_string;
  for (const auto& param : query_param_map) {
    // Supply additional Query Parameters as instructed by the provider.
    if (!query_params_string.empty()) {
      query_params_string += '&';
    }
    query_params_string += param.first + "=" + param.second;
  }
  return query_params_string;
}

// static
AutocompleteMatch BaseSearchProvider::CreateShortcutSearchSuggestion(
    const std::u16string& suggestion,
    AutocompleteMatchType::Type type,
    const TemplateURL* template_url,
    const SearchTermsData& search_terms_data) {
  // These calls use a number of default values.  For instance, they assume the
  // caller knows what it's doing and we set this match to look as if it was
  // received/created synchronously.
  SearchSuggestionParser::SuggestResult suggest_result(
      suggestion, type, /*suggest_type=*/omnibox::TYPE_NATIVE_CHROME,
      /*subtypes=*/{}, /*from_keyword=*/false,
      /*navigational_intent=*/omnibox::NAV_INTENT_NONE,
      /*relevance=*/0, /*relevance_from_server=*/false,
      /*input_text=*/std::u16string());
  suggest_result.set_received_after_last_keystroke(false);
  return CreateSearchSuggestion(nullptr, AutocompleteInput(),
                                /*in_keyword_mode=*/false, suggest_result,
                                template_url, search_terms_data, 0, false);
}

// static
AutocompleteMatch BaseSearchProvider::CreateOnDeviceSearchSuggestion(
    AutocompleteProvider* autocomplete_provider,
    const AutocompleteInput& input,
    const std::u16string& suggestion,
    int relevance,
    const TemplateURL* template_url,
    const SearchTermsData& search_terms_data,
    int accepted_suggestion,
    bool is_tail_suggestion) {
  AutocompleteMatchType::Type match_type;
  omnibox::SuggestType suggest_type = omnibox::TYPE_NATIVE_CHROME;
  std::u16string match_contents, match_contents_prefix;

  if (is_tail_suggestion) {
    match_type = AutocompleteMatchType::SEARCH_SUGGEST_TAIL;
    suggest_type = omnibox::TYPE_TAIL;
    std::u16string sanitized_suggestion =
        AutocompleteMatch::SanitizeString(suggestion);
    match_contents = GetMatchContentsForOnDeviceTailSuggestion(
        input.text(), sanitized_suggestion);

    DCHECK_GE(sanitized_suggestion.size(), match_contents.size());
    match_contents_prefix = sanitized_suggestion.substr(
        0, sanitized_suggestion.size() - match_contents.size());
  } else {
    match_type = AutocompleteMatchType::SEARCH_SUGGEST;
    suggest_type = omnibox::TYPE_QUERY;
    match_contents = suggestion;
  }

  SearchSuggestionParser::SuggestResult suggest_result(
      suggestion, match_type, suggest_type,
      /*subtypes=*/{omnibox::SUBTYPE_SUGGEST_2G_LITE}, match_contents,
      match_contents_prefix,
      /*annotation=*/std::u16string(),
      /*entity_info=*/omnibox::EntityInfo(),
      /*deletion_url=*/"",
      /*from_keyword=*/false,
      /*navigational_intent=*/omnibox::NAV_INTENT_NONE, relevance,
      /*relevance_from_server=*/false,
      /*should_prefetch=*/false,
      /*should_prerender=*/false,
      base::CollapseWhitespace(input.text(), false));
  // On device providers are asynchronous.
  suggest_result.set_received_after_last_keystroke(true);
  return CreateSearchSuggestion(
      autocomplete_provider, input, /*in_keyword_mode=*/false, suggest_result,
      template_url, search_terms_data, accepted_suggestion,
      /*append_extra_query_params_from_command_line=*/true);
}

// static
bool BaseSearchProvider::PageURLIsEligibleForSuggestRequest(
    const GURL& page_url,
    metrics::OmniboxEventProto::PageClassification page_classification) {
  return page_url.is_valid() && page_url.SchemeIsHTTPOrHTTPS() &&
         !omnibox::IsNTPPage(page_classification);
}

// static
bool BaseSearchProvider::CanSendSuggestRequest(
    metrics::OmniboxEventProto::PageClassification page_classification,
    const TemplateURL* template_url,
    const AutocompleteProviderClient* client) {
  if (!template_url || template_url->suggestions_url().empty()) {
    return false;
  }

  // Setting SuggestUrl the same as SearchUrl is a typical misconfiguration.
  // It's not possible for a URL to both provide a search results page and
  // suggested queries response (at least they have different format).  Most
  // like the user set the search URL correctly; it would be obvious if they did
  // not. Thus, it's likely that the suggest URL is wrong.  Because it would not
  // give a valid query suggestion response, don't bother sending queries to it
  // (otherwise user will quickly hit rate-limit for search queries, that will
  // harm valid search queries as well).
  if (template_url->suggestions_url() == template_url->url()) {
    return false;
  }

  // Don't make a suggest request if in incognito mode; unless for the Lens
  // searchboxes.
  if (client->IsOffTheRecord() &&
      !omnibox::IsLensSearchbox(page_classification)) {
    return false;
  }

  // Don't make a suggest request if suggest is not enabled; unless for the Lens
  // searchboxes.
  if (!client->SearchSuggestEnabled() &&
      !omnibox::IsLensSearchbox(page_classification)) {
    return false;
  }

  return true;
}

// static
bool BaseSearchProvider::CanSendSecureSuggestRequest(
    metrics::OmniboxEventProto::PageClassification page_classification,
    const TemplateURL* template_url,
    const SearchTermsData& search_terms_data,
    const AutocompleteProviderClient* client) {
  if (!CanSendSuggestRequest(page_classification, template_url, client)) {
    return false;
  }

  // Make sure we are sending the suggest request through a cryptographically
  // secure channel to prevent exposing the current page URL or personalized
  // results without encryption.
  const GURL& suggest_url =
      template_url->GenerateSuggestionURL(search_terms_data);
  if (!suggest_url.is_valid() || !suggest_url.SchemeIsCryptographic()) {
    return false;
  }

  // Don't make a suggest request if Google is not the default search engine.
  // Note that currently only the pre-populated Google search provider supports
  // zero-prefix suggestions. If other pre-populated search engines decide to
  // support it, revise this test accordingly.
  if (!search::TemplateURLIsGoogle(template_url, search_terms_data)) {
    return false;
  }

  return true;
}

// static
bool BaseSearchProvider::CanSendSuggestRequestWithPageURL(
    const GURL& current_page_url,
    metrics::OmniboxEventProto::PageClassification page_classification,
    const TemplateURL* template_url,
    const SearchTermsData& search_terms_data,
    const AutocompleteProviderClient* client) {
  if (!CanSendSecureSuggestRequest(page_classification, template_url,
                                   search_terms_data, client)) {
    return false;
  }

  // Forbid sending the current page URL to the suggest endpoint if
  // URL data collection is off; unless the current page is the provider's
  // Search Results Page; or for the Lens searchboxes.
  if (!client->IsUrlDataCollectionActive() &&
      !template_url->IsSearchURL(current_page_url, search_terms_data) &&
      !omnibox::IsLensSearchbox(page_classification)) {
    return false;
  }

  return true;
}

void BaseSearchProvider::DeleteMatch(const AutocompleteMatch& match) {
  DCHECK(match.deletable);
  // TODO (manukh): `GetAdditionalInfoForDebugging()` shouldn't be used for
  //   non-debugging purposes.
  if (!match.GetAdditionalInfoForDebugging(BaseSearchProvider::kDeletionUrlKey)
           .empty()) {
    // Remote personalized suggestions in OTR contexts are not OK.
    DCHECK(!client_->IsOffTheRecord());
    deletion_loaders_.push_back(
        client()
            ->GetRemoteSuggestionsService(/*create_if_necessary=*/true)
            ->StartDeletionRequest(
                match.GetAdditionalInfoForDebugging(
                    BaseSearchProvider::kDeletionUrlKey),
                /*is_off_the_record=*/false,
                base::BindOnce(&BaseSearchProvider::OnDeletionComplete,
                               base::Unretained(this))));
  }

  const TemplateURL* template_url =
      match.GetTemplateURL(client_->GetTemplateURLService(), false);
  // This may be nullptr if the template corresponding to the keyword has been
  // deleted or there is no keyword set.
  if (template_url != nullptr) {
    client_->DeleteMatchingURLsForKeywordFromHistory(template_url->id(),
                                                     match.contents);
  }

  // Immediately update the list of matches to show the match was deleted,
  // regardless of whether the server request actually succeeds.
  DeleteMatchFromMatches(match);
}

void BaseSearchProvider::AddProviderInfo(ProvidersInfo* provider_info) const {
  provider_info->push_back(metrics::OmniboxEventProto_ProviderInfo());
  metrics::OmniboxEventProto_ProviderInfo& new_entry = provider_info->back();
  new_entry.set_provider(AsOmniboxEventProviderType());
  new_entry.set_provider_done(done_);
}

// static
const char BaseSearchProvider::kRelevanceFromServerKey[] =
    "relevance_from_server";
const char BaseSearchProvider::kShouldPrefetchKey[] = "should_prefetch";
const char BaseSearchProvider::kShouldPrerenderKey[] = "should_prerender";
const char BaseSearchProvider::kDeletionUrlKey[] = "deletion_url";
const char BaseSearchProvider::kTrue[] = "true";
const char BaseSearchProvider::kFalse[] = "false";

BaseSearchProvider::~BaseSearchProvider() = default;

// static
std::u16string BaseSearchProvider::GetFillIntoEdit(
    const SearchSuggestionParser::SuggestResult& suggest_result,
    const TemplateURL* template_url) {
  std::u16string fill_into_edit;

  if (suggest_result.from_keyword())
    fill_into_edit.append(template_url->keyword() + u' ');

  fill_into_edit.append(suggest_result.suggestion());

  return fill_into_edit;
}

void BaseSearchProvider::SetDeletionURL(const std::string& deletion_url,
                                        AutocompleteMatch* match) {
  if (deletion_url.empty())
    return;

  TemplateURLService* template_url_service = client_->GetTemplateURLService();
  if (!template_url_service ||
      !template_url_service->GetDefaultSearchProvider())
    return;
  GURL url =
      template_url_service->GetDefaultSearchProvider()->GenerateSearchURL(
          template_url_service->search_terms_data());
  url = url.DeprecatedGetOriginAsURL().Resolve(deletion_url);
  if (url.is_valid()) {
    match->RecordAdditionalInfo(BaseSearchProvider::kDeletionUrlKey,
                                url.spec());
    match->deletable = true;
  }
}

void BaseSearchProvider::AddMatchToMap(
    const SearchSuggestionParser::SuggestResult& result,
    const AutocompleteInput& input,
    const TemplateURL* template_url,
    const SearchTermsData& search_terms_data,
    int accepted_suggestion,
    bool mark_as_deletable,
    bool in_keyword_mode,
    MatchMap* map) {
  AutocompleteMatch match = CreateSearchSuggestion(
      this, input, in_keyword_mode, result, template_url, search_terms_data,
      accepted_suggestion, ShouldAppendExtraParams(result));
  if (!match.destination_url.is_valid())
    return;
  if (match.IsSearchAimSuggestion() &&
      (!omnibox_feature_configs::AiMode::Get().allow_ai_mode_matches ||
       !AimEligibilityService::IsAimAllowedByPolicy(client_->GetPrefs()))) {
    return;
  }
  match.RecordAdditionalInfo(kRelevanceFromServerKey,
                             result.relevance_from_server() ? kTrue : kFalse);
  match.RecordAdditionalInfo(kShouldPrefetchKey,
                             result.should_prefetch() ? kTrue : kFalse);
  match.RecordAdditionalInfo(kShouldPrerenderKey,
                             result.should_prerender() ? kTrue : kFalse);
  SetDeletionURL(result.deletion_url(), &match);
  if (mark_as_deletable)
    match.deletable = true;

  // Only set scoring signals for eligible matches.
  if (match.IsMlSignalLoggingEligible()) {
    // Initialize the ML scoring signals for this suggestion if needed.
    if (!match.scoring_signals) {
      match.scoring_signals = std::make_optional<ScoringSignals>();
    }

    if (result.relevance_from_server()) {
      match.scoring_signals->set_search_suggest_relevance(result.relevance());
    }
    SearchScoringSignalsAnnotator::UpdateMatchTypeScoringSignals(match,
                                                                 input.text());
  }

  // Try to add `match` to `map`.
  // NOTE: Keep this ToLower() call in sync with url_database.cc.
  MatchKey match_key(
      std::make_tuple(base::i18n::ToLower(result.suggestion()),
                      match.search_terms_args->additional_query_params));
  const std::pair<MatchMap::iterator, bool> i(
      map->insert(std::make_pair(match_key, match)));
  if (i.second) {
    auto& added_match = i.first->second;
    // If the newly added match has non-empty additional query params and
    // another match with the same search terms and a unique non-empty
    // additional query params is already present in the map, proactively set
    // `stripped_destination_url` to be the same as `destination_url`.
    // Otherwise, `stripped_destination_url` will later be set by
    // `AutocompleteResult::ComputeStrippedDestinationURL()` which strips away
    // the additional query params from `destination_url` leaving only the
    // search terms. That would result in these matches to be erroneously
    // deduped despite having unique additional query params.
    // Note that the match previously added to the map will continue to get the
    // typical `stripped_destination_url` allowing it to be deduped with the
    // plain-text matches (i.e., with no additional query params) as expected.
    const auto& added_match_query = std::get<0>(match_key);
    const auto& added_match_query_params = std::get<1>(match_key);
    if (!added_match_query_params.empty()) {
      for (const auto& entry : *map) {
        const auto& existing_match_query = std::get<0>(entry.first);
        const auto& existing_match_query_params = std::get<1>(entry.first);
        if (existing_match_query == added_match_query &&
            !existing_match_query_params.empty() &&
            existing_match_query_params != added_match_query_params) {
          added_match.stripped_destination_url = added_match.destination_url;
          break;
        }
      }
    }
  } else {
    auto& existing_match = i.first->second;
    // If a duplicate match is already in the map, replace it with `match` if it
    // is more relevant.
    // NOTE: We purposefully do a direct relevance comparison here instead of
    // using AutocompleteMatch::MoreRelevant(), so that we'll prefer "items
    // added first" rather than "items alphabetically first" when the scores
    // are equal. The only case this matters is when a user has results with
    // the same score that differ only by capitalization; because the history
    // system returns results sorted by recency, this means we'll pick the most
    // recent such result even if the precision of our relevance score is too
    // low to distinguish the two.
    if (match.relevance > existing_match.relevance) {
      match.duplicate_matches.insert(match.duplicate_matches.end(),
                                     existing_match.duplicate_matches.begin(),
                                     existing_match.duplicate_matches.end());
      existing_match.duplicate_matches.clear();
      match.duplicate_matches.push_back(existing_match);
      existing_match = std::move(match);
    } else {
      if (match.keyword == existing_match.keyword) {
        // Old and new matches are from the same search provider. It is okay to
        // record one match's prefetch/prerender data onto a different match
        // (for the same query string) for the following reasons:
        // 1. Because the suggest server only sends down a query string from
        // which we construct a URL, rather than sending a full URL, and because
        // we construct URLs from query strings in the same way every time, the
        // URLs for the two matches will be the same. Therefore, we won't end up
        // prefetching/prerendering something the server didn't intend.
        // 2. Presumably the server sets the prefetch/prerender bit on a match
        // it thinks is sufficiently relevant that the user is likely to choose
        // it. Surely setting the prefetch/prerender bit on a match of even
        // higher relevance won't violate this assumption.
        const bool should_prefetch =
            result.should_prefetch() || ShouldPrefetch(existing_match);
        existing_match.RecordAdditionalInfo(kShouldPrefetchKey,
                                            should_prefetch ? kTrue : kFalse);
        const bool should_prerender =
            result.should_prerender() || ShouldPrerender(existing_match);
        existing_match.RecordAdditionalInfo(kShouldPrerenderKey,
                                            should_prerender ? kTrue : kFalse);
      }
      existing_match.duplicate_matches.push_back(std::move(match));
    }

    // Copy over necessary fields from the lower-ranking duplicate. Note that
    // this requires the lower-ranking duplicate being added last. See the use
    // of push_back above:

    // This is to avoid losing the Answers in Suggest information.
    const auto& less_relevant_duplicate_match =
        existing_match.duplicate_matches.back();
    if (less_relevant_duplicate_match.answer_template &&
        !existing_match.answer_template) {
      existing_match.actions = less_relevant_duplicate_match.actions;
      existing_match.answer_template =
          less_relevant_duplicate_match.answer_template;
      existing_match.answer_type = less_relevant_duplicate_match.answer_type;
      if (OmniboxFieldTrial::kAnswerActionsShowRichCard.Get()) {
        existing_match.suggestion_group_id =
            less_relevant_duplicate_match.suggestion_group_id;
      }
    }
    // This is to avoid having shopping categorical queries lose their images to
    // higher-relevance local history and verbatim matches. This works for the
    // shopping categorical queries because they only provide images at the
    // moment. That assumption may not hold in the future.
    // Ideally the entire `entity_info`, when available on a suggestion, should
    // be copied over. However `entity_info` is broken down to its constituents
    // in the constructor of SearchSuggestionParser::SuggestResult and used to
    // set individual fields on the AutocompleteMatch. This is in contrast to
    // Answers in Suggest which is kept on the match in its entirety. This is
    // partly because the entity name is used to set and classify the match
    // contents. Ideally `entity_info` should also be kept on the match in its
    // entirety so it can be carried over when deduplicating the matches here or
    // later in the Autocomplete process.
    // TODO(crbug.com/40276602): rework how `entity_info` is used in the match.
    if (base::FeatureList::IsEnabled(omnibox::kCategoricalSuggestions)) {
      if (!less_relevant_duplicate_match.image_url.is_empty() &&
          existing_match.image_url.is_empty()) {
        existing_match.image_url = less_relevant_duplicate_match.image_url;
      }
    }
    // This is to avoid having shopping categorical queries lose their subtypes
    // to higher-relevance local history and verbatim matches. The subtypes are
    // sent to the backend in the ChromeSearchboxStats proto via the gs_lcrp=
    // param when the user selects a suggestion. The subtypes may be used to
    // identify what the user selected so they can be suggested the next time,
    // i.e., if the user selects a decorated suggestion - which is accompanied
    // by specific subtypes - we want to show a decorated suggestion next time.
    if (base::FeatureList::IsEnabled(omnibox::kCategoricalSuggestions)) {
      existing_match.subtypes.insert(
          less_relevant_duplicate_match.subtypes.begin(),
          less_relevant_duplicate_match.subtypes.end());
    }
    // This is to avoid having `stripped_destination_url` being later set by
    // `AutocompleteResult::ComputeStrippedDestinationURL()` which strips away
    // the additional query params from `destination_url` leaving only the
    // search terms. That would result in these matches to be erroneously
    // deduped despite having unique additional query params.
    if (!less_relevant_duplicate_match.stripped_destination_url.is_empty() &&
        existing_match.stripped_destination_url.is_empty()) {
      existing_match.stripped_destination_url =
          less_relevant_duplicate_match.stripped_destination_url;
    }
  }
}

void BaseSearchProvider::DeleteMatchFromMatches(
    const AutocompleteMatch& match) {
  for (auto i(matches_.begin()); i != matches_.end(); ++i) {
    // Find the desired match to delete by checking the type and contents.
    // We can't check the destination URL, because the autocomplete controller
    // may have reformulated that. Not that while checking for matching
    // contents works for personalized suggestions, if more match types gain
    // deletion support, this algorithm may need to be re-examined.

    if (MatchTypeAndContentsAreEqual(match, *i)) {
      matches_.erase(i);
      break;
    }

    // Handle the case where the deleted match is only found within the
    // duplicate_matches sublist.
    std::vector<AutocompleteMatch>& duplicates = i->duplicate_matches;
    auto it =
        std::remove_if(duplicates.begin(), duplicates.end(),
                       [&match](const AutocompleteMatch& duplicate) {
                         return MatchTypeAndContentsAreEqual(match, duplicate);
                       });
    if (it != duplicates.end()) {
      duplicates.erase(it, duplicates.end());
      break;
    }
  }
}

void BaseSearchProvider::OnDeletionComplete(
    const network::SimpleURLLoader* source,
    const int response_code,
    std::unique_ptr<std::string> response_body) {
  RecordDeletionResult(response_code == 200);
  std::erase_if(
      deletion_loaders_,
      [source](const std::unique_ptr<network::SimpleURLLoader>& loader) {
        return loader.get() == source;
      });
}
