1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
|
// Copyright 2015 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/verbatim_match.h"
#include "base/containers/fixed_flat_set.h"
#include "components/omnibox/browser/autocomplete_classifier.h"
#include "components/omnibox/browser/autocomplete_input.h"
#include "components/omnibox/browser/autocomplete_match_classification.h"
#include "components/omnibox/browser/autocomplete_provider.h"
#include "components/omnibox/browser/autocomplete_provider_client.h"
#include "components/omnibox/browser/in_memory_url_index_types.h"
#include "components/search_engines/template_url_service.h"
#include "content/public/common/url_constants.h"
#include "extensions/buildflags/buildflags.h"
#include "third_party/metrics_proto/omnibox_scoring_signals.pb.h"
#include "url/gurl.h"
#include "url/url_constants.h"
#if BUILDFLAG(ENABLE_EXTENSIONS_CORE)
#include "extensions/common/constants.h"
#endif
namespace {
#if BUILDFLAG(IS_ANDROID)
// Note: On Android, restrict the verbatim URLs allowed to be default. We
// explicitly exclude schemes that may be used to execute Javascript code
// snippet in the context of the current page on mobile devices.
constexpr auto kAndroidNavigableSchemes =
base::MakeFixedFlatSet<std::string_view>({
url::kHttpScheme,
url::kHttpsScheme,
url::kAboutScheme,
content::kChromeUIScheme,
#if BUILDFLAG(ENABLE_EXTENSIONS_CORE)
// On desktop, extensions are always enabled, `kAndroidNavigableSchemes`
// is not used, and verbatim extension URLs are always allowed to be
// default. On mobile android, extensions are disabled,
// `ENABLE_EXTENSIONS_CORE` is false, and verbatim extension URLs are
// not allowed to be default. On desktop android, extensions are enabled
// and verbatim extension URLs are allowed to be default depending on
// `ENABLE_EXTENSIONS_CORE`.
extensions::kExtensionScheme,
#endif
});
#endif // BUILDFLAG(IS_ANDROID)
} // namespace
AutocompleteMatch VerbatimMatchForURL(
AutocompleteProvider* provider,
AutocompleteProviderClient* client,
const AutocompleteInput& input,
const GURL& destination_url,
const std::u16string& destination_description,
int verbatim_relevance) {
AutocompleteMatch match;
// If the caller is a provider and already knows where the verbatim match
// should go, construct the match directly, don't call Classify() on the
// input. Classify() runs all providers' synchronous passes. Some providers
// such as HistoryQuick can have a slow synchronous pass on some inputs.
if (provider != nullptr && destination_url.is_valid()) {
match =
VerbatimMatchForInput(provider, client, input, destination_url,
!AutocompleteInput::HasHTTPScheme(input.text()));
match.description = destination_description;
if (!match.description.empty())
match.description_class.push_back({0, ACMatchClassification::NONE});
} else {
client->Classify(input.text(), false, true,
input.current_page_classification(), &match, nullptr);
}
match.allowed_to_be_default_match = true;
// The default relevance to use for relevance match. Should be greater than
// all relevance matches returned by the ZeroSuggest server.
const int kDefaultVerbatimRelevance = 1300;
match.relevance =
verbatim_relevance >= 0 ? verbatim_relevance : kDefaultVerbatimRelevance;
return match;
}
AutocompleteMatch VerbatimMatchForInput(AutocompleteProvider* provider,
AutocompleteProviderClient* client,
const AutocompleteInput& input,
const GURL& destination_url,
bool trim_default_scheme) {
AutocompleteMatch match(provider, 0, false,
AutocompleteMatchType::URL_WHAT_YOU_TYPED);
if (destination_url.is_valid()) {
match.destination_url = destination_url;
// If the input explicitly contains "http://" or "https://", callers must
// set |trim_default_scheme| to false. Otherwise, |trim_default_scheme| may
// be either true or false.
if (input.added_default_scheme_to_typed_url()) {
DCHECK(!(trim_default_scheme &&
AutocompleteInput::HasHTTPSScheme(input.text())));
} else {
DCHECK(!(trim_default_scheme &&
AutocompleteInput::HasHTTPScheme(input.text())));
}
const url_formatter::FormatUrlType format_type =
input.added_default_scheme_to_typed_url()
? url_formatter::kFormatUrlOmitHTTPS
: url_formatter::kFormatUrlOmitHTTP;
std::u16string display_string(url_formatter::FormatUrl(
destination_url, url_formatter::kFormatUrlOmitDefaults & ~format_type,
base::UnescapeRule::SPACES, nullptr, nullptr, nullptr));
if (trim_default_scheme) {
AutocompleteProvider::TrimSchemePrefix(
&display_string, input.added_default_scheme_to_typed_url());
}
match.fill_into_edit =
AutocompleteInput::FormattedStringWithEquivalentMeaning(
destination_url, display_string, client->GetSchemeClassifier(),
nullptr);
// The what-you-typed match is generally only allowed to be default for
// URL inputs or when there is no default search provider. (It's also
// allowed to be default for UNKNOWN inputs where the destination is a known
// intranet site. In this case, |allowed_to_be_default_match| is revised in
// FixupExactSuggestion().)
const bool has_default_search_provider =
client->GetTemplateURLService() &&
client->GetTemplateURLService()->GetDefaultSearchProvider();
match.allowed_to_be_default_match =
(input.type() == metrics::OmniboxInputType::URL) ||
!has_default_search_provider;
#if BUILDFLAG(IS_ANDROID)
// Disallow non-navigable schemes to be default. This prevents javascript:
// snippets from being accidentally executed upon paste, refine, edit, etc.
match.allowed_to_be_default_match &=
kAndroidNavigableSchemes.contains(destination_url.scheme());
#endif
// NOTE: Don't set match.inline_autocompletion to something non-empty here;
// it's surprising and annoying.
// Try to highlight "innermost" match location. If we fix up "w" into
// "www.w.com", we want to highlight the fifth character, not the first.
// This relies on match.destination_url being the non-prefix-trimmed version
// of match.contents.
match.contents = display_string;
TermMatches termMatches = {{0, 0, input.text().length()}};
match.contents_class = ClassifyTermMatches(
termMatches, match.contents.size(),
ACMatchClassification::MATCH | ACMatchClassification::URL,
ACMatchClassification::URL);
// Only set scoring signals for eligible matches.
if (match.IsMlSignalLoggingEligible()) {
if (!match.scoring_signals) {
match.scoring_signals =
std::make_optional<::metrics::OmniboxScoringSignals>();
}
match.scoring_signals->set_is_verbatim(true);
}
}
return match;
}
|