blob: ee9c1bc19fc13b988257b15e8083768edd9bef45 [file] [log] [blame]
// Copyright 2020 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/omnibox/browser/zero_suggest_verbatim_match_provider.h"
#include "base/feature_list.h"
#include "base/strings/escape.h"
#include "components/omnibox/browser/autocomplete_match_classification.h"
#include "components/omnibox/browser/autocomplete_provider_client.h"
#include "components/omnibox/browser/autocomplete_provider_listener.h"
#include "components/omnibox/browser/verbatim_match.h"
#include "components/omnibox/common/omnibox_features.h"
#include "components/url_formatter/url_formatter.h"
namespace {
// The relevance score for verbatim match.
// Must outrank the QueryTiles relevance score.
const int kVerbatimMatchRelevanceScore = 1600;
// Returns whether specific context is eligible for a verbatim match.
// Only offer verbatim match on a site visit and SRP (no NTP etc).
bool IsVerbatimMatchEligible(
metrics::OmniboxEventProto::PageClassification context) {
// Only offer verbatim match on a site visit and SRP (no NTP etc).
return context == metrics::OmniboxEventProto::
SEARCH_RESULT_PAGE_DOING_SEARCH_TERM_REPLACEMENT ||
context == metrics::OmniboxEventProto::
SEARCH_RESULT_PAGE_NO_SEARCH_TERM_REPLACEMENT ||
context == metrics::OmniboxEventProto::ANDROID_SEARCH_WIDGET ||
context == metrics::OmniboxEventProto::ANDROID_SHORTCUTS_WIDGET ||
context == metrics::OmniboxEventProto::OTHER;
}
} // namespace
ZeroSuggestVerbatimMatchProvider::ZeroSuggestVerbatimMatchProvider(
AutocompleteProviderClient* client)
: AutocompleteProvider(TYPE_VERBATIM_MATCH), client_(client) {}
ZeroSuggestVerbatimMatchProvider::~ZeroSuggestVerbatimMatchProvider() = default;
void ZeroSuggestVerbatimMatchProvider::Start(const AutocompleteInput& input,
bool minimal_changes) {
Stop(true, false);
if (!IsVerbatimMatchEligible(input.current_page_classification()))
return;
// Only offer verbatim match after the user just focused the Omnibox,
// or if the input field is empty.
if (input.focus_type() == OmniboxFocusType::DEFAULT ||
input.focus_type() == OmniboxFocusType::DELETED_PERMANENT_TEXT)
return;
// For consistency with other zero-prefix providers.
const auto& page_url = input.current_url();
if (input.type() != metrics::OmniboxInputType::EMPTY &&
!(page_url.is_valid() &&
((page_url.scheme() == url::kHttpScheme) ||
(page_url.scheme() == url::kHttpsScheme) ||
(page_url.scheme() == url::kAboutScheme) ||
(page_url.scheme() ==
client_->GetEmbedderRepresentationOfAboutScheme())))) {
return;
}
AutocompleteInput verbatim_input = input;
verbatim_input.set_prevent_inline_autocomplete(true);
verbatim_input.set_allow_exact_keyword_match(false);
AutocompleteMatch match =
VerbatimMatchForURL(this, client_, verbatim_input, page_url,
input.current_title(), kVerbatimMatchRelevanceScore);
// Make sure the URL is formatted the same was as most visited sites.
auto format_types = AutocompleteMatch::GetFormatTypes(false, false);
match.contents = url_formatter::FormatUrl(page_url, format_types,
base::UnescapeRule::SPACES, nullptr,
nullptr, nullptr);
TermMatches term_matches;
if (input.text().length() > 0) {
term_matches = {{0, 0, input.text().length()}};
}
match.contents_class = ClassifyTermMatches(
term_matches, match.contents.size(),
ACMatchClassification::MATCH | ACMatchClassification::URL,
ACMatchClassification::URL);
// In the case of native pages, the classifier may replace the URL with an
// empty content, resulting with a verbatim match that does not point
// anywhere.
if (!match.destination_url.is_valid())
return;
match.provider = this;
matches_.push_back(match);
}