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 "chrome/browser/autocomplete/autocomplete_input.h" 12 #include "chrome/common/net/url_fixer_upper.h" 13 #include "chrome/common/url_constants.h" 14 15 namespace { 16 17 // This list should be kept in sync with chrome/common/url_constants.h. 18 // Only include useful sub-pages, confirmation alerts are not useful. 19 const char* const kChromeSettingsSubPages[] = { 20 chrome::kAutofillSubPage, 21 chrome::kClearBrowserDataSubPage, 22 chrome::kContentSettingsSubPage, 23 chrome::kContentSettingsExceptionsSubPage, 24 chrome::kImportDataSubPage, 25 chrome::kLanguageOptionsSubPage, 26 chrome::kPasswordManagerSubPage, 27 chrome::kResetProfileSettingsSubPage, 28 chrome::kSearchEnginesSubPage, 29 chrome::kSyncSetupSubPage, 30 #if defined(OS_CHROMEOS) 31 chrome::kInternetOptionsSubPage, 32 #endif 33 }; 34 35 } // namespace 36 37 const int BuiltinProvider::kRelevance = 860; 38 39 BuiltinProvider::BuiltinProvider(AutocompleteProviderListener* listener, 40 Profile* profile) 41 : AutocompleteProvider(listener, profile, 42 AutocompleteProvider::TYPE_BUILTIN) { 43 std::vector<std::string> builtins( 44 chrome::kChromeHostURLs, 45 chrome::kChromeHostURLs + chrome::kNumberOfChromeHostURLs); 46 std::sort(builtins.begin(), builtins.end()); 47 for (std::vector<std::string>::iterator i(builtins.begin()); 48 i != builtins.end(); ++i) 49 builtins_.push_back(ASCIIToUTF16(*i)); 50 base::string16 settings(ASCIIToUTF16(chrome::kChromeUISettingsHost) + 51 ASCIIToUTF16("/")); 52 for (size_t i = 0; i < arraysize(kChromeSettingsSubPages); i++) 53 builtins_.push_back(settings + ASCIIToUTF16(kChromeSettingsSubPages[i])); 54 } 55 56 void BuiltinProvider::Start(const AutocompleteInput& input, 57 bool minimal_changes) { 58 matches_.clear(); 59 if ((input.type() == AutocompleteInput::INVALID) || 60 (input.type() == AutocompleteInput::FORCED_QUERY) || 61 (input.type() == AutocompleteInput::QUERY)) 62 return; 63 64 const base::string16 kAbout = ASCIIToUTF16(chrome::kAboutScheme) + 65 ASCIIToUTF16(content::kStandardSchemeSeparator); 66 const base::string16 kChrome = ASCIIToUTF16(chrome::kChromeUIScheme) + 67 ASCIIToUTF16(content::kStandardSchemeSeparator); 68 69 const int kUrl = ACMatchClassification::URL; 70 const int kMatch = kUrl | ACMatchClassification::MATCH; 71 72 base::string16 text = input.text(); 73 bool starting_chrome = StartsWith(kChrome, text, false); 74 if (starting_chrome || StartsWith(kAbout, text, false)) { 75 ACMatchClassifications styles; 76 // Highlight the input portion matching "chrome://"; or if the user has 77 // input "about:" (with optional slashes), highlight the whole "chrome://". 78 const size_t kAboutSchemeLength = strlen(chrome::kAboutScheme); 79 bool highlight = starting_chrome || text.length() > kAboutSchemeLength; 80 styles.push_back(ACMatchClassification(0, highlight ? kMatch : kUrl)); 81 size_t offset = starting_chrome ? text.length() : kChrome.length(); 82 if (highlight) 83 styles.push_back(ACMatchClassification(offset, kUrl)); 84 // Include some common builtin chrome URLs as the user types the scheme. 85 AddMatch(ASCIIToUTF16(chrome::kChromeUIChromeURLsURL), base::string16(), 86 styles); 87 AddMatch(ASCIIToUTF16(chrome::kChromeUISettingsURL), base::string16(), 88 styles); 89 AddMatch(ASCIIToUTF16(chrome::kChromeUIVersionURL), base::string16(), 90 styles); 91 } else { 92 // Match input about: or chrome: URL input against builtin chrome URLs. 93 GURL url = URLFixerUpper::FixupURL(UTF16ToUTF8(text), std::string()); 94 // BuiltinProvider doesn't know how to suggest valid ?query or #fragment 95 // extensions to chrome: URLs. 96 if (url.SchemeIs(chrome::kChromeUIScheme) && url.has_host() && 97 !url.has_query() && !url.has_ref()) { 98 // Include the path for sub-pages (e.g. "chrome://settings/browser"). 99 base::string16 host_and_path = UTF8ToUTF16(url.host() + url.path()); 100 base::TrimString(host_and_path, ASCIIToUTF16("/").c_str(), 101 &host_and_path); 102 size_t match_length = kChrome.length() + host_and_path.length(); 103 for (Builtins::const_iterator i(builtins_.begin()); 104 (i != builtins_.end()) && (matches_.size() < kMaxMatches); ++i) { 105 if (StartsWith(*i, host_and_path, false)) { 106 ACMatchClassifications styles; 107 // Highlight the "chrome://" scheme, even for input "about:foo". 108 styles.push_back(ACMatchClassification(0, kMatch)); 109 base::string16 match_string = kChrome + *i; 110 if (match_string.length() > match_length) 111 styles.push_back(ACMatchClassification(match_length, kUrl)); 112 AddMatch(match_string, match_string.substr(match_length), styles); 113 } 114 } 115 } 116 } 117 118 for (size_t i = 0; i < matches_.size(); ++i) 119 matches_[i].relevance = kRelevance + matches_.size() - (i + 1); 120 if (!input.prevent_inline_autocomplete() && (matches_.size() == 1)) { 121 // If there's only one possible completion of the user's input and 122 // allowing completions is okay, give the match a high enough score to 123 // allow it to beat url-what-you-typed and be inlined. 124 matches_[0].relevance = 1250; 125 matches_[0].allowed_to_be_default_match = true; 126 } 127 } 128 129 BuiltinProvider::~BuiltinProvider() {} 130 131 void BuiltinProvider::AddMatch(const base::string16& match_string, 132 const base::string16& inline_completion, 133 const ACMatchClassifications& styles) { 134 AutocompleteMatch match(this, kRelevance, false, 135 AutocompleteMatchType::NAVSUGGEST); 136 match.fill_into_edit = match_string; 137 match.inline_autocompletion = inline_completion; 138 match.destination_url = GURL(match_string); 139 match.contents = match_string; 140 match.contents_class = styles; 141 matches_.push_back(match); 142 } 143