Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(104)

Side by Side Diff: chrome/browser/autocomplete/shortcuts_provider.cc

Issue 229733004: Omnibox: Make Bookmarks Set Inline_Autocompletion (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Peter's comments Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/autocomplete/shortcuts_provider.h" 5 #include "chrome/browser/autocomplete/shortcuts_provider.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <cmath> 8 #include <cmath>
9 #include <map> 9 #include <map>
10 #include <vector> 10 #include <vector>
(...skipping 29 matching lines...) Expand all
40 class DestinationURLEqualsURL { 40 class DestinationURLEqualsURL {
41 public: 41 public:
42 explicit DestinationURLEqualsURL(const GURL& url) : url_(url) {} 42 explicit DestinationURLEqualsURL(const GURL& url) : url_(url) {}
43 bool operator()(const AutocompleteMatch& match) const { 43 bool operator()(const AutocompleteMatch& match) const {
44 return match.destination_url == url_; 44 return match.destination_url == url_;
45 } 45 }
46 private: 46 private:
47 const GURL url_; 47 const GURL url_;
48 }; 48 };
49 49
50 // Like URLPrefix::BestURLPrefix() except also handles the prefix of
51 // "www.". This is needed because sometimes the string we're matching
52 // against here (which comes from |fill_into_edit|) can start with
53 // "www." without having a protocol at the beginning. Because "www."
54 // is not on the default prefix list, we test for it explicitly here
55 // and use that match if the default list didn't have a match or the
56 // default list's match was shorter than it could've been.
57 const URLPrefix* BestURLPrefixWithWWWCase(
58 const base::string16& text,
59 const base::string16& prefix_suffix) {
60 CR_DEFINE_STATIC_LOCAL(URLPrefix, www_prefix,
61 (base::ASCIIToUTF16("www."), 1));
62 const URLPrefix* best_prefix = URLPrefix::BestURLPrefix(text, prefix_suffix);
63 if ((best_prefix == NULL) ||
64 (best_prefix->num_components < www_prefix.num_components)) {
65 if (URLPrefix::PrefixMatch(www_prefix, text, prefix_suffix))
66 best_prefix = &www_prefix;
67 }
68 return best_prefix;
69 }
70
71 } // namespace 50 } // namespace
72 51
73 ShortcutsProvider::ShortcutsProvider(AutocompleteProviderListener* listener, 52 ShortcutsProvider::ShortcutsProvider(AutocompleteProviderListener* listener,
74 Profile* profile) 53 Profile* profile)
75 : AutocompleteProvider(listener, profile, 54 : AutocompleteProvider(listener, profile,
76 AutocompleteProvider::TYPE_SHORTCUTS), 55 AutocompleteProvider::TYPE_SHORTCUTS),
77 languages_(profile_->GetPrefs()->GetString(prefs::kAcceptLanguages)), 56 languages_(profile_->GetPrefs()->GetString(prefs::kAcceptLanguages)),
78 initialized_(false) { 57 initialized_(false) {
79 scoped_refptr<ShortcutsBackend> backend = 58 scoped_refptr<ShortcutsBackend> backend =
80 ShortcutsBackendFactory::GetForProfile(profile_); 59 ShortcutsBackendFactory::GetForProfile(profile_);
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
151 void ShortcutsProvider::GetMatches(const AutocompleteInput& input) { 130 void ShortcutsProvider::GetMatches(const AutocompleteInput& input) {
152 scoped_refptr<ShortcutsBackend> backend = 131 scoped_refptr<ShortcutsBackend> backend =
153 ShortcutsBackendFactory::GetForProfileIfExists(profile_); 132 ShortcutsBackendFactory::GetForProfileIfExists(profile_);
154 if (!backend.get()) 133 if (!backend.get())
155 return; 134 return;
156 // Get the URLs from the shortcuts database with keys that partially or 135 // Get the URLs from the shortcuts database with keys that partially or
157 // completely match the search term. 136 // completely match the search term.
158 base::string16 term_string(base::i18n::ToLower(input.text())); 137 base::string16 term_string(base::i18n::ToLower(input.text()));
159 DCHECK(!term_string.empty()); 138 DCHECK(!term_string.empty());
160 139
161 base::string16 fixed_up_term_string(term_string);
162 AutocompleteInput fixed_up_input(input); 140 AutocompleteInput fixed_up_input(input);
163 if (FixupUserInput(&fixed_up_input)) 141 FixupUserInput(&fixed_up_input);
164 fixed_up_term_string = fixed_up_input.text(); 142 const GURL& input_as_gurl = URLFixerUpper::FixupURL(
165 const GURL& term_string_as_gurl = URLFixerUpper::FixupURL( 143 base::UTF16ToUTF8(input.text()), std::string());
166 base::UTF16ToUTF8(term_string), std::string());
167 144
168 int max_relevance; 145 int max_relevance;
169 if (!OmniboxFieldTrial::ShortcutsScoringMaxRelevance( 146 if (!OmniboxFieldTrial::ShortcutsScoringMaxRelevance(
170 input.current_page_classification(), &max_relevance)) 147 input.current_page_classification(), &max_relevance))
171 max_relevance = AutocompleteResult::kLowestDefaultScore - 1; 148 max_relevance = AutocompleteResult::kLowestDefaultScore - 1;
172 149
173 for (ShortcutsBackend::ShortcutMap::const_iterator it = 150 for (ShortcutsBackend::ShortcutMap::const_iterator it =
174 FindFirstMatch(term_string, backend.get()); 151 FindFirstMatch(term_string, backend.get());
175 it != backend->shortcuts_map().end() && 152 it != backend->shortcuts_map().end() &&
176 StartsWith(it->first, term_string, true); ++it) { 153 StartsWith(it->first, term_string, true); ++it) {
177 // Don't return shortcuts with zero relevance. 154 // Don't return shortcuts with zero relevance.
178 int relevance = CalculateScore(term_string, it->second, max_relevance); 155 int relevance = CalculateScore(term_string, it->second, max_relevance);
179 if (relevance) { 156 if (relevance) {
180 matches_.push_back(ShortcutToACMatch( 157 matches_.push_back(ShortcutToACMatch(
181 it->second, relevance, term_string, fixed_up_term_string, 158 it->second, relevance, input, fixed_up_input, input_as_gurl));
182 term_string_as_gurl, input.prevent_inline_autocomplete()));
183 matches_.back().ComputeStrippedDestinationURL(profile_); 159 matches_.back().ComputeStrippedDestinationURL(profile_);
184 } 160 }
185 } 161 }
186 // Remove duplicates. 162 // Remove duplicates.
187 std::sort(matches_.begin(), matches_.end(), 163 std::sort(matches_.begin(), matches_.end(),
188 &AutocompleteMatch::DestinationSortFunc); 164 &AutocompleteMatch::DestinationSortFunc);
189 matches_.erase(std::unique(matches_.begin(), matches_.end(), 165 matches_.erase(std::unique(matches_.begin(), matches_.end(),
190 &AutocompleteMatch::DestinationsEqual), 166 &AutocompleteMatch::DestinationsEqual),
191 matches_.end()); 167 matches_.end());
192 // Find best matches. 168 // Find best matches.
(...skipping 21 matching lines...) Expand all
214 max_relevance = std::min(max_relevance, it->relevance); 190 max_relevance = std::min(max_relevance, it->relevance);
215 it->relevance = max_relevance; 191 it->relevance = max_relevance;
216 if (max_relevance > 1) 192 if (max_relevance > 1)
217 --max_relevance; 193 --max_relevance;
218 } 194 }
219 } 195 }
220 196
221 AutocompleteMatch ShortcutsProvider::ShortcutToACMatch( 197 AutocompleteMatch ShortcutsProvider::ShortcutToACMatch(
222 const history::ShortcutsDatabase::Shortcut& shortcut, 198 const history::ShortcutsDatabase::Shortcut& shortcut,
223 int relevance, 199 int relevance,
224 const base::string16& term_string, 200 const AutocompleteInput& input,
225 const base::string16& fixed_up_term_string, 201 const AutocompleteInput& fixed_up_input,
226 const GURL& term_string_as_gurl, 202 const GURL& input_as_gurl) {
227 const bool prevent_inline_autocomplete) { 203 DCHECK(!input.text().empty());
228 DCHECK(!term_string.empty());
229 AutocompleteMatch match; 204 AutocompleteMatch match;
230 match.provider = this; 205 match.provider = this;
231 match.relevance = relevance; 206 match.relevance = relevance;
232 match.deletable = true; 207 match.deletable = true;
233 match.fill_into_edit = shortcut.match_core.fill_into_edit; 208 match.fill_into_edit = shortcut.match_core.fill_into_edit;
234 match.destination_url = shortcut.match_core.destination_url; 209 match.destination_url = shortcut.match_core.destination_url;
235 DCHECK(match.destination_url.is_valid()); 210 DCHECK(match.destination_url.is_valid());
236 match.contents = shortcut.match_core.contents; 211 match.contents = shortcut.match_core.contents;
237 match.contents_class = AutocompleteMatch::ClassificationsFromString( 212 match.contents_class = AutocompleteMatch::ClassificationsFromString(
238 shortcut.match_core.contents_class); 213 shortcut.match_core.contents_class);
239 match.description = shortcut.match_core.description; 214 match.description = shortcut.match_core.description;
240 match.description_class = AutocompleteMatch::ClassificationsFromString( 215 match.description_class = AutocompleteMatch::ClassificationsFromString(
241 shortcut.match_core.description_class); 216 shortcut.match_core.description_class);
242 match.transition = 217 match.transition =
243 static_cast<content::PageTransition>(shortcut.match_core.transition); 218 static_cast<content::PageTransition>(shortcut.match_core.transition);
244 match.type = static_cast<AutocompleteMatch::Type>(shortcut.match_core.type); 219 match.type = static_cast<AutocompleteMatch::Type>(shortcut.match_core.type);
245 match.keyword = shortcut.match_core.keyword; 220 match.keyword = shortcut.match_core.keyword;
246 match.RecordAdditionalInfo("number of hits", shortcut.number_of_hits); 221 match.RecordAdditionalInfo("number of hits", shortcut.number_of_hits);
247 match.RecordAdditionalInfo("last access time", shortcut.last_access_time); 222 match.RecordAdditionalInfo("last access time", shortcut.last_access_time);
248 match.RecordAdditionalInfo("original input text", 223 match.RecordAdditionalInfo("original input text",
249 base::UTF16ToUTF8(shortcut.text)); 224 base::UTF16ToUTF8(shortcut.text));
250 225
251 // Set |inline_autocompletion| and |allowed_to_be_default_match| if possible. 226 // Set |inline_autocompletion| and |allowed_to_be_default_match| if possible.
252 // If the match is a search query this is easy: simply check whether the 227 // If the match is a search query this is easy: simply check whether the
253 // user text is a prefix of the query. If the match is a navigation, we 228 // user text is a prefix of the query. If the match is a navigation, we
254 // assume the fill_into_edit looks something like a URL, so we use 229 // assume the fill_into_edit looks something like a URL, so we use
255 // BestURLPrefix() to try and strip off any prefixes that the user might 230 // URLPrefix::ComputeMatchStartAndInlineAutocompleteOffset() to try and strip
256 // not think would change the meaning, but would otherwise prevent inline 231 // off any prefixes that the user might not think would change the meaning,
257 // autocompletion. This allows, for example, the input of "foo.c" to 232 // but would otherwise prevent inline autocompletion. This allows, for
258 // autocomplete to "foo.com" for a fill_into_edit of "http://foo.com". 233 // example, the input of "foo.c" to autocomplete to "foo.com" for a
234 // fill_into_edit of "http://foo.com".
259 if (AutocompleteMatch::IsSearchType(match.type)) { 235 if (AutocompleteMatch::IsSearchType(match.type)) {
260 if (StartsWith(match.fill_into_edit, term_string, false)) { 236 if (StartsWith(match.fill_into_edit, input.text(), false)) {
261 match.inline_autocompletion = 237 match.inline_autocompletion =
262 match.fill_into_edit.substr(term_string.length()); 238 match.fill_into_edit.substr(input.text().length());
263 match.allowed_to_be_default_match = 239 match.allowed_to_be_default_match =
264 !prevent_inline_autocomplete || match.inline_autocompletion.empty(); 240 !input.prevent_inline_autocomplete() ||
241 match.inline_autocompletion.empty();
265 } 242 }
266 } else { 243 } else {
267 const URLPrefix* best_prefix = 244 size_t match_start, inline_autocomplete_offset;
268 BestURLPrefixWithWWWCase(match.fill_into_edit, term_string); 245 URLPrefix::ComputeMatchStartAndInlineAutocompleteOffset(
269 const base::string16* matching_string = &term_string; 246 input, fixed_up_input, true, match.fill_into_edit,
270 // If we failed to find a best_prefix initially, try again using a 247 &match_start, &inline_autocomplete_offset);
271 // fixed-up version of the user input. This is especially useful to 248 if (inline_autocomplete_offset != base::string16::npos) {
272 // get about: URLs to inline against chrome:// shortcuts. (about: 249 match.inline_autocompletion =
273 // URLs are fixed up to the chrome:// scheme.) 250 match.fill_into_edit.substr(inline_autocomplete_offset);
274 if ((best_prefix == NULL) && !fixed_up_term_string.empty() &&
275 (fixed_up_term_string != term_string)) {
276 best_prefix = BestURLPrefixWithWWWCase(
277 match.fill_into_edit, fixed_up_term_string);
278 matching_string = &fixed_up_term_string;
279 }
280 if (best_prefix != NULL) {
281 match.inline_autocompletion = match.fill_into_edit.substr(
282 best_prefix->prefix.length() + matching_string->length());
283 match.allowed_to_be_default_match = 251 match.allowed_to_be_default_match =
284 !prevent_inline_autocomplete || match.inline_autocompletion.empty(); 252 !HistoryProvider::PreventInlineAutocomplete(input) ||
253 match.inline_autocompletion.empty();
285 } else { 254 } else {
286 // Also allow a user's input to be marked as default if it would be fixed 255 // Also allow a user's input to be marked as default if it would be fixed
287 // up to the same thing as the fill_into_edit. This handles cases like 256 // up to the same thing as the fill_into_edit. This handles cases like
288 // the user input containing a trailing slash absent in fill_into_edit. 257 // the user input containing a trailing slash absent in fill_into_edit.
289 match.allowed_to_be_default_match = (term_string_as_gurl == 258 match.allowed_to_be_default_match = (input_as_gurl ==
290 URLFixerUpper::FixupURL(base::UTF16ToUTF8(match.fill_into_edit), 259 URLFixerUpper::FixupURL(base::UTF16ToUTF8(match.fill_into_edit),
291 std::string())); 260 std::string()));
292 } 261 }
293 } 262 }
294 263
295 // Try to mark pieces of the contents and description as matches if they 264 // Try to mark pieces of the contents and description as matches if they
296 // appear in |term_string|. 265 // appear in |input.text()|.
266 const base::string16 term_string = base::i18n::ToLower(input.text());
297 WordMap terms_map(CreateWordMapForString(term_string)); 267 WordMap terms_map(CreateWordMapForString(term_string));
298 if (!terms_map.empty()) { 268 if (!terms_map.empty()) {
299 match.contents_class = ClassifyAllMatchesInString(term_string, terms_map, 269 match.contents_class = ClassifyAllMatchesInString(term_string, terms_map,
300 match.contents, match.contents_class); 270 match.contents, match.contents_class);
301 match.description_class = ClassifyAllMatchesInString(term_string, terms_map, 271 match.description_class = ClassifyAllMatchesInString(term_string, terms_map,
302 match.description, match.description_class); 272 match.description, match.description_class);
303 } 273 }
304 return match; 274 return match;
305 } 275 }
306 276
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
453 // (1.0 / each 5 additional hits), up to a maximum of 5x as long. 423 // (1.0 / each 5 additional hits), up to a maximum of 5x as long.
454 const double kMaxDecaySpeedDivisor = 5.0; 424 const double kMaxDecaySpeedDivisor = 5.0;
455 const double kNumUsesPerDecaySpeedDivisorIncrement = 5.0; 425 const double kNumUsesPerDecaySpeedDivisorIncrement = 5.0;
456 double decay_divisor = std::min(kMaxDecaySpeedDivisor, 426 double decay_divisor = std::min(kMaxDecaySpeedDivisor,
457 (shortcut.number_of_hits + kNumUsesPerDecaySpeedDivisorIncrement - 1) / 427 (shortcut.number_of_hits + kNumUsesPerDecaySpeedDivisorIncrement - 1) /
458 kNumUsesPerDecaySpeedDivisorIncrement); 428 kNumUsesPerDecaySpeedDivisorIncrement);
459 429
460 return static_cast<int>((base_score / exp(decay_exponent / decay_divisor)) + 430 return static_cast<int>((base_score / exp(decay_exponent / decay_divisor)) +
461 0.5); 431 0.5);
462 } 432 }
OLDNEW
« no previous file with comments | « chrome/browser/autocomplete/shortcuts_provider.h ('k') | chrome/browser/autocomplete/shortcuts_provider_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698