blob: 0a7d0ff549c06e26132dc37ca88ee0eb51e3bd41 [file] [log] [blame]
// 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 "components/omnibox/browser/autocomplete_grouper_sections.h"
#include <algorithm>
#include <memory>
#include <optional>
#include "base/containers/contains.h"
#include "base/dcheck_is_on.h"
#include "base/debug/crash_logging.h"
#include "base/debug/dump_without_crashing.h"
#include "base/notreached.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "components/omnibox/browser/autocomplete_grouper_groups.h"
#include "components/omnibox/browser/autocomplete_match.h"
#include "components/omnibox/browser/autocomplete_match_type.h"
#include "components/omnibox/browser/omnibox_field_trial.h"
#include "components/omnibox/common/omnibox_feature_configs.h"
#include "third_party/omnibox_proto/groups.pb.h"
namespace {
constexpr size_t kMobileMostVisitedTilesLimit = 10;
constexpr bool is_android = !!BUILDFLAG(IS_ANDROID);
constexpr size_t kMaxSuggestionsPerUnscopedExtension = 4;
constexpr size_t kMaxExtensions = 2;
}
Section::Section(size_t limit,
Groups groups,
omnibox::GroupConfigMap& group_configs,
omnibox::GroupConfig_SideType side_type)
: limit_(limit),
groups_(std::move(groups)),
group_configs_(group_configs),
side_type_(side_type) {
#if DCHECK_IS_ON()
// Make sure all the `GroupId`s in the `Group`s have the same `RenderType`.
for (const auto& group : groups_) {
std::optional<omnibox::GroupConfig_RenderType> last_render_type;
for (const auto& [group_id, _] : group.group_id_limits_and_counts()) {
const auto& render_type = group_configs[group_id].render_type();
DCHECK_EQ(last_render_type.value_or(render_type), render_type)
<< "GroupId " << group_id
<< " has different RenderType than the previous one.";
last_render_type = render_type;
}
}
#endif // DCHECK_IS_ON()
}
Section::~Section() = default;
// static
ACMatches Section::GroupMatches(PSections sections, ACMatches& matches) {
for (auto& section : sections) {
section->InitFromMatches(matches);
}
for (const auto& match : matches) {
DCHECK(match.suggestion_group_id.has_value());
for (const auto& section : sections) {
if (section->Add(match))
break;
}
}
ACMatches grouped_matches = {};
for (auto& section : sections) {
for (auto& group : section->groups_) {
group.GroupMatches();
for (AutocompleteMatch* match : group.matches()) {
grouped_matches.push_back(std::move(*match));
}
}
}
return grouped_matches;
}
Groups::iterator Section::FindGroup(const AutocompleteMatch& match) {
// Check if match is allowed in this `Section` by its GroupId `SideType`.
const auto& group_id = match.suggestion_group_id.value();
if (group_configs_[group_id].side_type() != side_type_) {
return groups_.end();
}
return std::ranges::find_if(
groups_, [&](const auto& group) { return group.CanAdd(match); });
}
bool Section::Add(const AutocompleteMatch& match) {
if (count_ >= limit_) {
return false;
}
auto group_itr = FindGroup(match);
if (group_itr == groups_.end()) {
return false;
}
group_itr->Add(match);
count_++;
return true;
}
ZpsSection::ZpsSection(size_t limit,
Groups groups,
omnibox::GroupConfigMap& group_configs,
omnibox::GroupConfig_SideType side_type)
: Section(limit, std::move(groups), group_configs, side_type) {}
void ZpsSection::InitFromMatches(ACMatches& matches) {
// Ensure matches are sorted in the order of their potential containing
// groups. E.g., if `groups_ = {group 1, group 2}, matches that can be added
// to group 1 must appear before those that can only be added to group 2.
size_t last_group_index = 0;
for (const auto& match : matches) {
auto group_itr = FindGroup(match);
if (group_itr == groups_.end()) {
continue;
}
size_t current_group_index = std::distance(groups_.begin(), group_itr);
if (current_group_index < last_group_index) {
const std::string match_type =
AutocompleteMatchType::ToString(match.type);
const std::string match_group_id =
omnibox::GroupId_Name(match.suggestion_group_id.value());
const std::string match_relevance = base::NumberToString(match.relevance);
const std::string group_description = base::JoinString(
[&]() {
std::vector<std::string> transformed;
std::ranges::transform(
group_itr->group_id_limits_and_counts(),
std::back_inserter(transformed), [](const auto& pair) {
return omnibox::GroupId_Name(pair.first) + " (" +
base::NumberToString(
static_cast<int>(pair.second.limit)) +
")";
});
return transformed;
}(),
", ");
SCOPED_CRASH_KEY_STRING32("ZpsSection", "match-type", match_type);
SCOPED_CRASH_KEY_STRING32("ZpsSection", "match-group-id", match_group_id);
SCOPED_CRASH_KEY_STRING32("ZpsSection", "match-relevance",
match_relevance);
SCOPED_CRASH_KEY_STRING32("ZpsSection", "group-description",
group_description);
base::debug::DumpWithoutCrashing();
#if DCHECK_IS_ON()
NOTREACHED() << "Match with type " << match_type << " and group id "
<< match_group_id << " and relevance " << match_relevance
<< " is not sorted correctly while being added to Group "
<< group_description;
#endif // DCHECK_IS_ON()
}
last_group_index = current_group_index;
}
}
ZpsSectionWithLocalHistory::ZpsSectionWithLocalHistory(
size_t limit,
Groups groups,
omnibox::GroupConfigMap& group_configs)
: ZpsSection(limit, std::move(groups), group_configs) {}
void ZpsSectionWithLocalHistory::InitFromMatches(ACMatches& matches) {
// Sort matches in the order of their potential containing groups. E.g., if
// `groups_ = {group 1, group 2}, this sorts all matches that can be added to
// group 1 before those that can only be added to group 2.
std::ranges::stable_sort(matches, std::less<int>{}, [&](const auto& match) {
// Don't have to handle `FindGroup()` returning `groups_.end()` since
// those matches won't be added to the section anyways.
return std::distance(groups_.begin(), FindGroup(match));
});
ZpsSection::InitFromMatches(matches);
}
// Number of matches that fit in the visible section of the screen.
// This number includes the Default match, shown in the top section.
// The default match needs to be kept separate, because it should not be
// moved when we group suggestions by Search vs URL.
// TODO(b/328617350): plumb the value via AutocompleteInput.
/* static */ size_t AndroidNonZPSSection::num_visible_matches_{6};
AndroidNonZPSSection::AndroidNonZPSSection(
bool show_only_search_suggestions,
omnibox::GroupConfigMap& group_configs)
: Section(
15,
{
// Default match Group, not part of the Grouping.
Group(1,
{
{omnibox::GROUP_SEARCH, 1},
{omnibox::GROUP_OTHER_NAVS, 1},
{omnibox::GROUP_MOBILE_RICH_ANSWER,
OmniboxFieldTrial::kAnswerActionsShowRichCard.Get() &&
!OmniboxFieldTrial::
kAnswerActionsShowAboveKeyboard.Get()
? 1
: 0},
},
/*is_zps=*/false),
// Top Group / above the keyboard.
Group(num_visible_matches_ - 1,
{
{omnibox::GROUP_SEARCH, 14},
{omnibox::GROUP_OTHER_NAVS,
show_only_search_suggestions ? 0 : 14},
},
/*is_zps=*/false),
// Dedicated Group for rich answer card just above the fold.
Group(1,
{
{omnibox::GROUP_MOBILE_RICH_ANSWER,
OmniboxFieldTrial::kAnswerActionsShowRichCard.Get() &&
OmniboxFieldTrial::
kAnswerActionsShowAboveKeyboard.Get()
? 1
: 0},
},
/*is_zps=*/false),
// Bottom Group, up to the Section limit.
Group(14,
{
{omnibox::GROUP_SEARCH, 14},
{omnibox::GROUP_OTHER_NAVS,
show_only_search_suggestions ? 0 : 14},
},
/*is_zps=*/false),
},
group_configs) {}
void AndroidNonZPSSection::InitFromMatches(ACMatches& matches) {
auto rich_answer_match = std::ranges::find_if(
matches,
[&](const auto& match) { return match.answer_template.has_value(); });
bool has_rich_answer = rich_answer_match != matches.end();
if (!has_rich_answer) {
return;
}
bool has_url = std::ranges::any_of(matches, [](const auto& match) {
return !AutocompleteMatch::IsSearchType(match.type);
});
bool hide_if_urls_present =
!OmniboxFieldTrial::kAnswerActionsShowIfUrlsPresent.Get();
if (has_url && hide_if_urls_present) {
rich_answer_match->suggestion_group_id = omnibox::GROUP_SEARCH;
}
if (!OmniboxFieldTrial::kAnswerActionsShowRichCard.Get() ||
!OmniboxFieldTrial::kAnswerActionsShowAboveKeyboard.Get()) {
return;
}
auto& above_keyboard_group = groups_[1];
above_keyboard_group.set_limit(above_keyboard_group.limit() - 1);
}
AndroidHubZPSSection::AndroidHubZPSSection(
omnibox::GroupConfigMap& group_configs)
: Section(5,
{
Group(5,
{
{omnibox::GROUP_MOBILE_OPEN_TABS, 5},
}),
},
group_configs) {}
AndroidHubNonZPSSection::AndroidHubNonZPSSection(
omnibox::GroupConfigMap& group_configs)
: Section(
35,
{
// Reserve most of the spots for open tabs.
Group(20,
{
{omnibox::GROUP_MOBILE_OPEN_TABS, 20},
},
/*is_zps=*/false),
Group(5,
{
{omnibox::GROUP_MOBILE_BOOKMARKS, 5},
},
/*is_zps=*/false),
// LINT.IfChange(HubHistorySectionSlots)
Group(5,
{
{omnibox::GROUP_MOBILE_HISTORY, 5},
},
/*is_zps=*/false),
// LINT.ThenChange(//components/omnibox/browser/history_quick_provider.cc:HubHistoryMaxMatches)
// Fallback to search suggestions at the bottom of the results.
Group(5,
{
{omnibox::GROUP_SEARCH, 5},
},
/*is_zps=*/false),
},
group_configs) {}
void AndroidNTPZpsSection::InitFromMatches(ACMatches& matches) {
bool mia_suggestions_detected =
std::ranges::any_of(matches, [&](const auto& match) {
return match.suggestion_group_id.value_or(omnibox::GROUP_INVALID) ==
omnibox::GROUP_MIA_RECOMMENDATIONS;
});
if (omnibox_feature_configs::MiaZPS::Get()
.suppress_psuggest_backfill_with_mia &&
mia_suggestions_detected) {
// Hacky and delicate, but follows a pattern found in other sections of this
// file.
const_cast<Group::LimitAndCount&>(
groups_[1].group_id_limits_and_counts().at(
omnibox::GROUP_PERSONALIZED_ZERO_SUGGEST))
.limit = 0;
}
ZpsSectionWithLocalHistory::InitFromMatches(matches);
}
AndroidNTPZpsSection::AndroidNTPZpsSection(
omnibox::GroupConfigMap& group_configs,
bool mia_enabled)
: ZpsSectionWithLocalHistory(
30,
{
Group(1,
{
{omnibox::GROUP_MOBILE_CLIPBOARD, 1},
}),
Group(OmniboxFieldTrial::kOmniboxNumNtpZpsRecentSearches.Get(),
{
{
omnibox::GROUP_PERSONALIZED_ZERO_SUGGEST_WITH_MIA,
mia_enabled
? OmniboxFieldTrial::
kOmniboxNumNtpZpsRecentSearches.Get()
: 0,
},
{
omnibox::GROUP_MIA_RECOMMENDATIONS,
mia_enabled
? OmniboxFieldTrial::
kOmniboxNumNtpZpsRecentSearches.Get()
: 0,
},
{omnibox::GROUP_PERSONALIZED_ZERO_SUGGEST,
OmniboxFieldTrial::kOmniboxNumNtpZpsRecentSearches
.Get()},
}),
Group(OmniboxFieldTrial::kOmniboxNumNtpZpsTrendingSearches.Get(),
{
{omnibox::GROUP_TRENDS,
OmniboxFieldTrial::kOmniboxNumNtpZpsTrendingSearches
.Get()},
}),
},
group_configs) {}
AndroidSRPZpsSection::AndroidSRPZpsSection(
omnibox::GroupConfigMap& group_configs)
: ZpsSection(
15,
{
Group(1,
{
{omnibox::GROUP_MOBILE_SEARCH_READY_OMNIBOX, 1},
}),
Group(1,
{
{omnibox::GROUP_MOBILE_CLIPBOARD, 1},
}),
Group(OmniboxFieldTrial::kOmniboxNumSrpZpsRelatedSearches.Get(),
{
{omnibox::GROUP_PREVIOUS_SEARCH_RELATED,
OmniboxFieldTrial::kOmniboxNumSrpZpsRelatedSearches
.Get()},
}),
Group(OmniboxFieldTrial::kOmniboxNumSrpZpsRecentSearches.Get(),
{
{omnibox::GROUP_PERSONALIZED_ZERO_SUGGEST,
OmniboxFieldTrial::kOmniboxNumSrpZpsRecentSearches
.Get()},
}),
},
group_configs) {}
AndroidWebZpsSection::AndroidWebZpsSection(
omnibox::GroupConfigMap& group_configs)
: ZpsSectionWithMVTiles(
15, // Excludes MV tile count (calculated at runtime).
{
Group(1,
{
{omnibox::GROUP_MOBILE_SEARCH_READY_OMNIBOX, 1},
}),
Group(1,
{
{omnibox::GROUP_MOBILE_CLIPBOARD, 1},
}),
Group(OmniboxFieldTrial::kOmniboxNumWebZpsMostVisitedUrls.Get(),
{
{omnibox::GROUP_MOBILE_MOST_VISITED,
OmniboxFieldTrial::kOmniboxNumWebZpsMostVisitedUrls
.Get()},
}),
Group(OmniboxFieldTrial::kOmniboxNumWebZpsRelatedSearches.Get(),
{
{omnibox::GROUP_VISITED_DOC_RELATED,
OmniboxFieldTrial::kOmniboxNumWebZpsRelatedSearches
.Get()},
}),
Group(OmniboxFieldTrial::kOmniboxNumWebZpsRecentSearches.Get(),
{
{omnibox::GROUP_PERSONALIZED_ZERO_SUGGEST,
OmniboxFieldTrial::kOmniboxNumWebZpsRecentSearches
.Get()},
}),
},
group_configs) {}
DesktopNTPZpsSection::DesktopNTPZpsSection(
omnibox::GroupConfigMap& group_configs,
size_t limit,
bool mia_enabled)
: ZpsSectionWithLocalHistory(
limit,
{
Group(
8,
{
{omnibox::GROUP_PERSONALIZED_ZERO_SUGGEST_WITH_MIA,
mia_enabled ? 8 : 0},
{omnibox::GROUP_MIA_RECOMMENDATIONS, mia_enabled ? 8 : 0},
{omnibox::GROUP_PERSONALIZED_ZERO_SUGGEST, 8},
}),
Group(8,
{
{omnibox::GROUP_TRENDS, 8},
}),
},
group_configs) {}
DesktopNTPZpsIPHSection::DesktopNTPZpsIPHSection(
omnibox::GroupConfigMap& group_configs)
: ZpsSection(1,
{
Group(1,
{
{omnibox::GROUP_ZERO_SUGGEST_IN_PRODUCT_HELP, 1},
}),
},
group_configs) {}
DesktopZpsUnscopedExtensionSection::DesktopZpsUnscopedExtensionSection(
omnibox::GroupConfigMap& group_configs)
: ZpsSection(kMaxSuggestionsPerUnscopedExtension * kMaxExtensions,
{
Group(kMaxSuggestionsPerUnscopedExtension,
{
{omnibox::GROUP_UNSCOPED_EXTENSION_1,
kMaxSuggestionsPerUnscopedExtension},
}),
Group(kMaxSuggestionsPerUnscopedExtension,
{
{omnibox::GROUP_UNSCOPED_EXTENSION_2,
kMaxSuggestionsPerUnscopedExtension},
}),
},
group_configs) {}
DesktopSecondaryNTPZpsSection::DesktopSecondaryNTPZpsSection(
omnibox::GroupConfigMap& group_configs)
: ZpsSection(
(omnibox_feature_configs::RealboxContextualAndTrendingSuggestions::
Get()
.enabled)
? omnibox_feature_configs::
RealboxContextualAndTrendingSuggestions::Get()
.total_limit
: 3,
{
Group(
3,
{
{omnibox::GROUP_PREVIOUS_SEARCH_RELATED_ENTITY_CHIPS, 3},
}),
Group(
(omnibox_feature_configs::
RealboxContextualAndTrendingSuggestions::Get()
.enabled)
? omnibox_feature_configs::
RealboxContextualAndTrendingSuggestions::Get()
.contextual_suggestions_limit
: 0,
{
{omnibox::GROUP_PREVIOUS_SEARCH_RELATED,
(omnibox_feature_configs::
RealboxContextualAndTrendingSuggestions::Get()
.enabled)
? omnibox_feature_configs::
RealboxContextualAndTrendingSuggestions::Get()
.contextual_suggestions_limit
: 0},
}),
Group(
(omnibox_feature_configs::
RealboxContextualAndTrendingSuggestions::Get()
.enabled)
? omnibox_feature_configs::
RealboxContextualAndTrendingSuggestions::Get()
.trending_suggestions_limit
: 0,
{
{omnibox::GROUP_TRENDS,
(omnibox_feature_configs::
RealboxContextualAndTrendingSuggestions::Get()
.enabled)
? omnibox_feature_configs::
RealboxContextualAndTrendingSuggestions::Get()
.trending_suggestions_limit
: 0},
}),
},
group_configs,
omnibox::GroupConfig_SideType_SECONDARY) {}
DesktopSRPZpsSection::DesktopSRPZpsSection(
omnibox::GroupConfigMap& group_configs,
size_t max_suggestions,
size_t search_limit,
size_t url_limit,
size_t contextual_action_limit)
: ZpsSection(
max_suggestions,
{
Group(
search_limit,
{
{omnibox::GROUP_PREVIOUS_SEARCH_RELATED, search_limit},
{omnibox::GROUP_PERSONALIZED_ZERO_SUGGEST, search_limit},
}),
Group(url_limit,
{
{omnibox::GROUP_MOST_VISITED, url_limit},
}),
#if 1
Group(contextual_action_limit,
{
{omnibox::GROUP_CONTEXTUAL_SEARCH_ACTION,
contextual_action_limit},
}),
#endif
},
group_configs) {
}
DesktopWebURLZpsSection::DesktopWebURLZpsSection(
omnibox::GroupConfigMap& group_configs,
size_t limit)
: ZpsSection(limit,
{
Group(limit,
{
{omnibox::GROUP_MOST_VISITED, limit},
}),
},
group_configs) {}
DesktopWebSearchZpsSection::DesktopWebSearchZpsSection(
omnibox::GroupConfigMap& group_configs,
size_t limit,
size_t contextual_action_limit,
size_t contextual_search_limit)
: Section(limit,
{
Group(limit,
{
{omnibox::GROUP_VISITED_DOC_RELATED, limit},
{omnibox::GROUP_PERSONALIZED_ZERO_SUGGEST, limit},
}),
Group(contextual_action_limit,
{
{omnibox::GROUP_CONTEXTUAL_SEARCH_ACTION,
contextual_action_limit},
}),
Group(contextual_search_limit,
{
{omnibox::GROUP_CONTEXTUAL_SEARCH,
contextual_search_limit},
}),
},
group_configs) {}
DesktopWebSearchZpsContextualOnlySection::
DesktopWebSearchZpsContextualOnlySection(
omnibox::GroupConfigMap& group_configs,
size_t contextual_action_limit,
size_t contextual_search_limit)
: Section(contextual_action_limit + contextual_search_limit,
{
Group(contextual_action_limit,
{
{omnibox::GROUP_CONTEXTUAL_SEARCH_ACTION,
contextual_action_limit},
}),
Group(contextual_search_limit,
{
{omnibox::GROUP_CONTEXTUAL_SEARCH,
contextual_search_limit},
}),
},
group_configs) {}
DesktopLensContextualZpsSection::DesktopLensContextualZpsSection(
omnibox::GroupConfigMap& group_configs)
: ZpsSection(5,
{
Group(5,
{
{omnibox::GROUP_CONTEXTUAL_SEARCH, 5},
}),
},
group_configs) {}
DesktopLensMultimodalZpsSection::DesktopLensMultimodalZpsSection(
omnibox::GroupConfigMap& group_configs)
: ZpsSection(8,
{
Group(8,
{
{omnibox::GROUP_MULTIMODAL, 8},
}),
},
group_configs) {}
DesktopComposeboxZpsSection::DesktopComposeboxZpsSection(
omnibox::GroupConfigMap& group_configs,
size_t max_suggestions,
size_t max_aim_suggestions,
size_t max_contextual_suggestions)
: ZpsSection(
max_suggestions,
{
Group(max_suggestions,
{{omnibox::GROUP_MIA_RECOMMENDATIONS, max_aim_suggestions},
{omnibox::GROUP_PERSONALIZED_ZERO_SUGGEST_WITH_MIA,
max_aim_suggestions},
{omnibox::GROUP_CONTEXTUAL_SEARCH,
max_contextual_suggestions}}),
},
group_configs) {}
ToolbeltSection::ToolbeltSection(omnibox::GroupConfigMap& group_configs)
: ZpsSection(1,
{
Group(1,
{
{omnibox::GROUP_SEARCH_TOOLBELT, 1},
}),
},
group_configs) {}
DesktopNonZpsSection::DesktopNonZpsSection(
omnibox::GroupConfigMap& group_configs)
: Section(10,
{
Group(1,
{
{omnibox::GROUP_STARTER_PACK, 1},
{omnibox::GROUP_SEARCH, 1},
{omnibox::GROUP_OTHER_NAVS, 1},
},
/*is_zps=*/false,
/*is_default=*/true),
Group(9,
{
{omnibox::GROUP_STARTER_PACK, 9},
},
/*is_zps=*/false),
Group(9,
{
{omnibox::GROUP_SEARCH, 9},
{omnibox::GROUP_HISTORY_CLUSTER, 1},
},
/*is_zps=*/false),
Group(7,
{
{omnibox::GROUP_OTHER_NAVS, 7},
},
/*is_zps=*/false),
},
group_configs) {}
void DesktopNonZpsSection::InitFromMatches(ACMatches& matches) {
auto& default_group = groups_[0];
auto& search_group = groups_[2];
auto& nav_group = groups_[3];
// Determine if `matches` contains any searches.
bool has_search = std::ranges::any_of(
matches, [&](const auto& match) { return search_group.CanAdd(match); });
// Determine if the default match will be a search.
auto default_match = std::ranges::find_if(
matches, [&](const auto& match) { return default_group.CanAdd(match); });
bool default_is_search =
default_match != matches.end() && search_group.CanAdd(*default_match);
// Find the 1st nav's index.
size_t first_nav_index = std::distance(
matches.begin(), std::ranges::find_if(matches, [&](const auto& match) {
return nav_group.CanAdd(match);
}));
// Show at most 8 suggestions if doing so includes navs; otherwise show 9 or
// 10, if doing so doesn't include navs.
limit_ = std::clamp<size_t>(first_nav_index, 8, 10);
// Show at least 1 search, either in the default group or the search group.
if (has_search && !default_is_search) {
DCHECK_GE(limit_, 2U);
nav_group.set_limit(limit_ - 2);
}
}
ZpsSectionWithMVTiles::ZpsSectionWithMVTiles(
size_t limit,
Groups groups,
omnibox::GroupConfigMap& group_configs)
: ZpsSection(limit, std::move(groups), group_configs) {}
void ZpsSectionWithMVTiles::InitFromMatches(ACMatches& matches) {
size_t tile_count = std::count_if(
matches.begin(), matches.end(), [](const AutocompleteMatch& m) {
return m.suggestion_group_id.value_or(omnibox::GROUP_INVALID) ==
omnibox::GROUP_MOBILE_MOST_VISITED;
});
const size_t max_most_visited_tiles =
is_android ? OmniboxFieldTrial::kOmniboxNumWebZpsMostVisitedUrls.Get()
: kMobileMostVisitedTilesLimit;
// In the event we find more MV tiles than we can accommodate, trim the limit.
limit_ += std::min(tile_count, max_most_visited_tiles);
// Note that the horizontal render group takes a single slot in vertical list:
// we therefore count it as an individual item, meaning this list:
// [ URL_WHAT_YOU_TYPED ]
// [ [MV] [MV] [MV] [MV] ]
// [ SEARCH_SUGGEST ]
// has 3 elements built from 6 AutocompleteMatch objects.
limit_ -= (tile_count ? 1 : 0);
ZpsSection::InitFromMatches(matches);
}
void IOSNTPZpsSection::InitFromMatches(ACMatches& matches) {
bool mia_suggestions_detected =
std::ranges::any_of(matches, [&](const auto& match) {
return match.suggestion_group_id.value_or(omnibox::GROUP_INVALID) ==
omnibox::GROUP_MIA_RECOMMENDATIONS;
});
if (omnibox_feature_configs::MiaZPS::Get()
.suppress_psuggest_backfill_with_mia &&
mia_suggestions_detected) {
// Hacky and delicate, but follows a pattern found in other sections of this
// file.
const_cast<Group::LimitAndCount&>(
groups_[1].group_id_limits_and_counts().at(
omnibox::GROUP_PERSONALIZED_ZERO_SUGGEST))
.limit = 0;
}
ZpsSectionWithLocalHistory::InitFromMatches(matches);
}
IOSNTPZpsSection::IOSNTPZpsSection(omnibox::GroupConfigMap& group_configs,
bool mia_enabled)
: ZpsSectionWithLocalHistory(
26,
{
Group(1,
{
{omnibox::GROUP_MOBILE_CLIPBOARD, 1},
}),
Group(20,
{
{omnibox::GROUP_PERSONALIZED_ZERO_SUGGEST_WITH_MIA,
mia_enabled ? 20 : 0},
{omnibox::GROUP_MIA_RECOMMENDATIONS,
mia_enabled ? 20 : 0},
{omnibox::GROUP_PERSONALIZED_ZERO_SUGGEST, 20},
}),
Group(5,
{
{omnibox::GROUP_TRENDS, 5},
}),
},
group_configs) {}
IOSSRPZpsSection::IOSSRPZpsSection(omnibox::GroupConfigMap& group_configs)
: ZpsSectionWithMVTiles(
20,
{
Group(1,
{
{omnibox::GROUP_MOBILE_SEARCH_READY_OMNIBOX, 1},
}),
Group(1,
{
{omnibox::GROUP_MOBILE_CLIPBOARD, 1},
}),
Group(kMobileMostVisitedTilesLimit,
{
{omnibox::GROUP_MOBILE_MOST_VISITED,
kMobileMostVisitedTilesLimit},
}),
Group(8,
{
{omnibox::GROUP_PREVIOUS_SEARCH_RELATED, 8},
}),
Group(20,
{
{omnibox::GROUP_PERSONALIZED_ZERO_SUGGEST, 20},
}),
},
group_configs) {}
IOSWebZpsSection::IOSWebZpsSection(omnibox::GroupConfigMap& group_configs)
: ZpsSectionWithMVTiles(
20,
{
Group(1,
{
{omnibox::GROUP_MOBILE_SEARCH_READY_OMNIBOX, 1},
}),
Group(1,
{
{omnibox::GROUP_MOBILE_CLIPBOARD, 1},
}),
Group(kMobileMostVisitedTilesLimit,
{
{omnibox::GROUP_MOBILE_MOST_VISITED,
kMobileMostVisitedTilesLimit},
}),
Group(8,
{
{omnibox::GROUP_VISITED_DOC_RELATED, 8},
}),
Group(20,
{
{omnibox::GROUP_PERSONALIZED_ZERO_SUGGEST, 20},
}),
},
group_configs) {}
IOSLensMultimodalZpsSection::IOSLensMultimodalZpsSection(
omnibox::GroupConfigMap& group_configs)
: ZpsSection(10,
{
Group(10,
{
{omnibox::GROUP_MULTIMODAL, 10},
}),
},
group_configs) {}