Roll src/third_party/WebKit eac3800:0237a66 (svn 202606:202607)
[chromium-blink-merge.git] / components / omnibox / browser / builtin_provider.cc
blob6e3dde614582d62d5fdca78453b35b9bbba9f386
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "components/omnibox/browser/builtin_provider.h"
7 #include <algorithm>
9 #include "base/strings/string_util.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "components/metrics/proto/omnibox_input_type.pb.h"
12 #include "components/omnibox/browser/autocomplete_input.h"
13 #include "components/omnibox/browser/autocomplete_provider_client.h"
14 #include "components/omnibox/browser/history_provider.h"
15 #include "components/url_formatter/url_fixer.h"
17 const int BuiltinProvider::kRelevance = 860;
19 BuiltinProvider::BuiltinProvider(AutocompleteProviderClient* client)
20 : AutocompleteProvider(AutocompleteProvider::TYPE_BUILTIN),
21 client_(client) {
22 builtins_ = client_->GetBuiltinURLs();
25 void BuiltinProvider::Start(const AutocompleteInput& input,
26 bool minimal_changes) {
27 matches_.clear();
28 if (input.from_omnibox_focus() ||
29 (input.type() == metrics::OmniboxInputType::INVALID) ||
30 (input.type() == metrics::OmniboxInputType::FORCED_QUERY) ||
31 (input.type() == metrics::OmniboxInputType::QUERY))
32 return;
34 const size_t kAboutSchemeLength = strlen(url::kAboutScheme);
35 const base::string16 kAbout =
36 base::ASCIIToUTF16(url::kAboutScheme) +
37 base::ASCIIToUTF16(url::kStandardSchemeSeparator);
38 const base::string16 embedderAbout =
39 base::UTF8ToUTF16(client_->GetEmbedderRepresentationOfAboutScheme()) +
40 base::ASCIIToUTF16(url::kStandardSchemeSeparator);
42 const int kUrl = ACMatchClassification::URL;
43 const int kMatch = kUrl | ACMatchClassification::MATCH;
45 const base::string16 text = input.text();
46 bool starting_about = base::StartsWith(embedderAbout, text,
47 base::CompareCase::INSENSITIVE_ASCII);
48 if (starting_about ||
49 base::StartsWith(kAbout, text, base::CompareCase::INSENSITIVE_ASCII)) {
50 ACMatchClassifications styles;
51 // Highlight the input portion matching |embedderAbout|; or if the user has
52 // input "about:" (with optional slashes), highlight the whole
53 // |embedderAbout|.
54 bool highlight = starting_about || text.length() > kAboutSchemeLength;
55 styles.push_back(ACMatchClassification(0, highlight ? kMatch : kUrl));
56 size_t offset = starting_about ? text.length() : embedderAbout.length();
57 if (highlight)
58 styles.push_back(ACMatchClassification(offset, kUrl));
59 // Include some common builtin URLs as the user types the scheme.
60 for (base::string16 url : client_->GetBuiltinsToProvideAsUserTypes())
61 AddMatch(url, base::string16(), styles);
62 } else {
63 // Match input about: or |embedderAbout| URL input against builtin URLs.
64 GURL url = url_formatter::FixupURL(base::UTF16ToUTF8(text), std::string());
65 // BuiltinProvider doesn't know how to suggest valid ?query or #fragment
66 // extensions to builtin URLs.
67 if (url.SchemeIs(
68 client_->GetEmbedderRepresentationOfAboutScheme().c_str()) &&
69 url.has_host() && !url.has_query() && !url.has_ref()) {
70 // Suggest about:blank for substrings, taking URL fixup into account.
71 // Chrome does not support trailing slashes or paths for about:blank.
72 const base::string16 blank_host = base::ASCIIToUTF16("blank");
73 const base::string16 host = base::UTF8ToUTF16(url.host());
74 if (base::StartsWith(text, base::ASCIIToUTF16(url::kAboutScheme),
75 base::CompareCase::INSENSITIVE_ASCII) &&
76 base::StartsWith(blank_host, host,
77 base::CompareCase::INSENSITIVE_ASCII) &&
78 (url.path().length() <= 1) &&
79 !base::EndsWith(text, base::ASCIIToUTF16("/"),
80 base::CompareCase::SENSITIVE)) {
81 ACMatchClassifications styles;
82 styles.push_back(ACMatchClassification(0, kMatch));
83 base::string16 match = base::ASCIIToUTF16(url::kAboutBlankURL);
84 // Measure the length of the matching host after the "about:" scheme.
85 const size_t corrected_length = kAboutSchemeLength + 1 + host.length();
86 if (blank_host.length() > host.length())
87 styles.push_back(ACMatchClassification(corrected_length, kUrl));
88 AddMatch(match, match.substr(corrected_length), styles);
91 // Include the path for sub-pages (e.g. "chrome://settings/browser").
92 base::string16 host_and_path = base::UTF8ToUTF16(url.host() + url.path());
93 base::TrimString(host_and_path, base::ASCIIToUTF16("/"), &host_and_path);
94 size_t match_length = embedderAbout.length() + host_and_path.length();
95 for (Builtins::const_iterator i(builtins_.begin());
96 (i != builtins_.end()) && (matches_.size() < kMaxMatches); ++i) {
97 if (base::StartsWith(*i, host_and_path,
98 base::CompareCase::INSENSITIVE_ASCII)) {
99 ACMatchClassifications styles;
100 // Highlight |embedderAbout|, even for input "about:foo".
101 styles.push_back(ACMatchClassification(0, kMatch));
102 base::string16 match_string = embedderAbout + *i;
103 if (match_string.length() > match_length)
104 styles.push_back(ACMatchClassification(match_length, kUrl));
105 AddMatch(match_string, match_string.substr(match_length), styles);
111 for (size_t i = 0; i < matches_.size(); ++i)
112 matches_[i].relevance = kRelevance + matches_.size() - (i + 1);
113 if (!HistoryProvider::PreventInlineAutocomplete(input) &&
114 (matches_.size() == 1)) {
115 // If there's only one possible completion of the user's input and
116 // allowing completions is okay, give the match a high enough score to
117 // allow it to beat url-what-you-typed and be inlined.
118 matches_[0].relevance = 1250;
119 matches_[0].allowed_to_be_default_match = true;
123 BuiltinProvider::~BuiltinProvider() {}
125 void BuiltinProvider::AddMatch(const base::string16& match_string,
126 const base::string16& inline_completion,
127 const ACMatchClassifications& styles) {
128 AutocompleteMatch match(this, kRelevance, false,
129 AutocompleteMatchType::NAVSUGGEST);
130 match.fill_into_edit = match_string;
131 match.inline_autocompletion = inline_completion;
132 match.destination_url = GURL(match_string);
133 match.contents = match_string;
134 match.contents_class = styles;
135 matches_.push_back(match);