| OLD | NEW | 
 | (Empty) | 
|    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. |  | 
|    4  |  | 
|    5 #include "chrome/browser/autocomplete/builtin_provider.h" |  | 
|    6  |  | 
|    7 #include <algorithm> |  | 
|    8  |  | 
|    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/autocomplete_input.h" |  | 
|   13 #include "components/omnibox/autocomplete_provider_client.h" |  | 
|   14 #include "components/omnibox/history_provider.h" |  | 
|   15 #include "components/url_fixer/url_fixer.h" |  | 
|   16  |  | 
|   17 const int BuiltinProvider::kRelevance = 860; |  | 
|   18  |  | 
|   19 BuiltinProvider::BuiltinProvider(AutocompleteProviderClient* client) |  | 
|   20     : AutocompleteProvider(AutocompleteProvider::TYPE_BUILTIN), |  | 
|   21       client_(client) { |  | 
|   22   builtins_ = client_->GetBuiltinURLs(); |  | 
|   23 } |  | 
|   24  |  | 
|   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; |  | 
|   33  |  | 
|   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); |  | 
|   41  |  | 
|   42   const int kUrl = ACMatchClassification::URL; |  | 
|   43   const int kMatch = kUrl | ACMatchClassification::MATCH; |  | 
|   44  |  | 
|   45   base::string16 text = input.text(); |  | 
|   46   bool starting_about = base::StartsWith(embedderAbout, text, false); |  | 
|   47   if (starting_about || base::StartsWith(kAbout, text, false)) { |  | 
|   48     ACMatchClassifications styles; |  | 
|   49     // Highlight the input portion matching |embedderAbout|; or if the user has |  | 
|   50     // input "about:" (with optional slashes), highlight the whole |  | 
|   51     // |embedderAbout|. |  | 
|   52     bool highlight = starting_about || text.length() > kAboutSchemeLength; |  | 
|   53     styles.push_back(ACMatchClassification(0, highlight ? kMatch : kUrl)); |  | 
|   54     size_t offset = starting_about ? text.length() : embedderAbout.length(); |  | 
|   55     if (highlight) |  | 
|   56       styles.push_back(ACMatchClassification(offset, kUrl)); |  | 
|   57     // Include some common builtin URLs as the user types the scheme. |  | 
|   58     for (base::string16 url : client_->GetBuiltinsToProvideAsUserTypes()) |  | 
|   59       AddMatch(url, base::string16(), styles); |  | 
|   60   } else { |  | 
|   61     // Match input about: or |embedderAbout| URL input against builtin URLs. |  | 
|   62     GURL url = url_fixer::FixupURL(base::UTF16ToUTF8(text), std::string()); |  | 
|   63     // BuiltinProvider doesn't know how to suggest valid ?query or #fragment |  | 
|   64     // extensions to builtin URLs. |  | 
|   65     if (url.SchemeIs( |  | 
|   66             client_->GetEmbedderRepresentationOfAboutScheme().c_str()) && |  | 
|   67         url.has_host() && !url.has_query() && !url.has_ref()) { |  | 
|   68       // Suggest about:blank for substrings, taking URL fixup into account. |  | 
|   69       // Chrome does not support trailing slashes or paths for about:blank. |  | 
|   70       const base::string16 blank_host = base::ASCIIToUTF16("blank"); |  | 
|   71       const base::string16 host = base::UTF8ToUTF16(url.host()); |  | 
|   72       if (base::StartsWith(text, base::ASCIIToUTF16(url::kAboutScheme), |  | 
|   73                            false) && |  | 
|   74           base::StartsWith(blank_host, host, false) && |  | 
|   75           (url.path().length() <= 1) && |  | 
|   76           !base::EndsWith(text, base::ASCIIToUTF16("/"), false)) { |  | 
|   77         ACMatchClassifications styles; |  | 
|   78         styles.push_back(ACMatchClassification(0, kMatch)); |  | 
|   79         base::string16 match = base::ASCIIToUTF16(url::kAboutBlankURL); |  | 
|   80         // Measure the length of the matching host after the "about:" scheme. |  | 
|   81         const size_t corrected_length = kAboutSchemeLength + 1 + host.length(); |  | 
|   82         if (blank_host.length() > host.length()) |  | 
|   83           styles.push_back(ACMatchClassification(corrected_length, kUrl)); |  | 
|   84         AddMatch(match, match.substr(corrected_length), styles); |  | 
|   85       } |  | 
|   86  |  | 
|   87       // Include the path for sub-pages (e.g. "chrome://settings/browser"). |  | 
|   88       base::string16 host_and_path = base::UTF8ToUTF16(url.host() + url.path()); |  | 
|   89       base::TrimString(host_and_path, base::ASCIIToUTF16("/"), &host_and_path); |  | 
|   90       size_t match_length = embedderAbout.length() + host_and_path.length(); |  | 
|   91       for (Builtins::const_iterator i(builtins_.begin()); |  | 
|   92           (i != builtins_.end()) && (matches_.size() < kMaxMatches); ++i) { |  | 
|   93         if (base::StartsWith(*i, host_and_path, false)) { |  | 
|   94           ACMatchClassifications styles; |  | 
|   95           // Highlight |embedderAbout|, even for input "about:foo". |  | 
|   96           styles.push_back(ACMatchClassification(0, kMatch)); |  | 
|   97           base::string16 match_string = embedderAbout + *i; |  | 
|   98           if (match_string.length() > match_length) |  | 
|   99             styles.push_back(ACMatchClassification(match_length, kUrl)); |  | 
|  100           AddMatch(match_string, match_string.substr(match_length), styles); |  | 
|  101         } |  | 
|  102       } |  | 
|  103     } |  | 
|  104   } |  | 
|  105  |  | 
|  106   for (size_t i = 0; i < matches_.size(); ++i) |  | 
|  107     matches_[i].relevance = kRelevance + matches_.size() - (i + 1); |  | 
|  108   if (!HistoryProvider::PreventInlineAutocomplete(input) && |  | 
|  109       (matches_.size() == 1)) { |  | 
|  110     // If there's only one possible completion of the user's input and |  | 
|  111     // allowing completions is okay, give the match a high enough score to |  | 
|  112     // allow it to beat url-what-you-typed and be inlined. |  | 
|  113     matches_[0].relevance = 1250; |  | 
|  114     matches_[0].allowed_to_be_default_match = true; |  | 
|  115   } |  | 
|  116 } |  | 
|  117  |  | 
|  118 BuiltinProvider::~BuiltinProvider() {} |  | 
|  119  |  | 
|  120 void BuiltinProvider::AddMatch(const base::string16& match_string, |  | 
|  121                                const base::string16& inline_completion, |  | 
|  122                                const ACMatchClassifications& styles) { |  | 
|  123   AutocompleteMatch match(this, kRelevance, false, |  | 
|  124                           AutocompleteMatchType::NAVSUGGEST); |  | 
|  125   match.fill_into_edit = match_string; |  | 
|  126   match.inline_autocompletion = inline_completion; |  | 
|  127   match.destination_url = GURL(match_string); |  | 
|  128   match.contents = match_string; |  | 
|  129   match.contents_class = styles; |  | 
|  130   matches_.push_back(match); |  | 
|  131 } |  | 
| OLD | NEW |