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

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

Issue 17261012: Omnibox: Add Field Trial to Make Shortcuts More Aggressive (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: clean up comments Created 7 years, 6 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>
11 11
12 #include "base/i18n/break_iterator.h" 12 #include "base/i18n/break_iterator.h"
13 #include "base/i18n/case_conversion.h" 13 #include "base/i18n/case_conversion.h"
14 #include "base/logging.h" 14 #include "base/logging.h"
15 #include "base/metrics/histogram.h" 15 #include "base/metrics/histogram.h"
16 #include "base/prefs/pref_service.h" 16 #include "base/prefs/pref_service.h"
17 #include "base/strings/string_number_conversions.h" 17 #include "base/strings/string_number_conversions.h"
18 #include "base/strings/string_util.h" 18 #include "base/strings/string_util.h"
19 #include "base/strings/utf_string_conversions.h" 19 #include "base/strings/utf_string_conversions.h"
20 #include "base/time.h" 20 #include "base/time.h"
21 #include "chrome/browser/autocomplete/autocomplete_input.h" 21 #include "chrome/browser/autocomplete/autocomplete_input.h"
22 #include "chrome/browser/autocomplete/autocomplete_provider_listener.h" 22 #include "chrome/browser/autocomplete/autocomplete_provider_listener.h"
23 #include "chrome/browser/autocomplete/autocomplete_result.h" 23 #include "chrome/browser/autocomplete/autocomplete_result.h"
24 #include "chrome/browser/history/history_notifications.h" 24 #include "chrome/browser/history/history_notifications.h"
25 #include "chrome/browser/history/history_service.h" 25 #include "chrome/browser/history/history_service.h"
26 #include "chrome/browser/history/history_service_factory.h" 26 #include "chrome/browser/history/history_service_factory.h"
27 #include "chrome/browser/history/shortcuts_backend_factory.h" 27 #include "chrome/browser/history/shortcuts_backend_factory.h"
28 #include "chrome/browser/omnibox/omnibox_field_trial.h"
28 #include "chrome/browser/profiles/profile.h" 29 #include "chrome/browser/profiles/profile.h"
29 #include "chrome/common/pref_names.h" 30 #include "chrome/common/pref_names.h"
30 #include "chrome/common/url_constants.h" 31 #include "chrome/common/url_constants.h"
31 #include "googleurl/src/url_parse.h" 32 #include "googleurl/src/url_parse.h"
32 33
33 namespace { 34 namespace {
34 35
35 class RemoveMatchPredicate { 36 class RemoveMatchPredicate {
36 public: 37 public:
37 explicit RemoveMatchPredicate(const std::set<GURL>& urls) 38 explicit RemoveMatchPredicate(const std::set<GURL>& urls)
38 : urls_(urls) { 39 : urls_(urls) {
39 } 40 }
40 bool operator()(const AutocompleteMatch& match) { 41 bool operator()(const AutocompleteMatch& match) {
41 return urls_.find(match.destination_url) != urls_.end(); 42 return urls_.find(match.destination_url) != urls_.end();
42 } 43 }
43 private: 44 private:
44 // Lifetime of the object is less than the lifetime of passed |urls|, so 45 // Lifetime of the object is less than the lifetime of passed |urls|, so
45 // it is safe to store reference. 46 // it is safe to store reference.
46 const std::set<GURL>& urls_; 47 const std::set<GURL>& urls_;
47 }; 48 };
48 49
49 } // namespace 50 } // namespace
50 51
51 ShortcutsProvider::ShortcutsProvider(AutocompleteProviderListener* listener, 52 ShortcutsProvider::ShortcutsProvider(AutocompleteProviderListener* listener,
52 Profile* profile) 53 Profile* profile)
53 : AutocompleteProvider(listener, profile, 54 : AutocompleteProvider(listener, profile,
54 AutocompleteProvider::TYPE_SHORTCUTS), 55 AutocompleteProvider::TYPE_SHORTCUTS),
55 languages_(profile_->GetPrefs()->GetString(prefs::kAcceptLanguages)), 56 languages_(profile_->GetPrefs()->GetString(prefs::kAcceptLanguages)),
56 initialized_(false) { 57 initialized_(false),
58 max_relevance_(AutocompleteResult::kLowestDefaultScore - 1) {
57 scoped_refptr<history::ShortcutsBackend> backend = 59 scoped_refptr<history::ShortcutsBackend> backend =
58 ShortcutsBackendFactory::GetForProfile(profile_); 60 ShortcutsBackendFactory::GetForProfile(profile_);
59 if (backend.get()) { 61 if (backend.get()) {
60 backend->AddObserver(this); 62 backend->AddObserver(this);
61 if (backend->initialized()) 63 if (backend->initialized())
62 initialized_ = true; 64 initialized_ = true;
63 } 65 }
66 int max_relevance;
67 if (OmniboxFieldTrial::ShortcutsScoringMaxRelevance(&max_relevance))
68 max_relevance_ = max_relevance;
64 } 69 }
65 70
66 void ShortcutsProvider::Start(const AutocompleteInput& input, 71 void ShortcutsProvider::Start(const AutocompleteInput& input,
67 bool minimal_changes) { 72 bool minimal_changes) {
68 matches_.clear(); 73 matches_.clear();
69 74
70 if ((input.type() == AutocompleteInput::INVALID) || 75 if ((input.type() == AutocompleteInput::INVALID) ||
71 (input.type() == AutocompleteInput::FORCED_QUERY)) 76 (input.type() == AutocompleteInput::FORCED_QUERY))
72 return; 77 return;
73 78
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
162 matches_.push_back(ShortcutToACMatch(relevance, term_string, it->second)); 167 matches_.push_back(ShortcutToACMatch(relevance, term_string, it->second));
163 } 168 }
164 std::partial_sort(matches_.begin(), 169 std::partial_sort(matches_.begin(),
165 matches_.begin() + 170 matches_.begin() +
166 std::min(AutocompleteProvider::kMaxMatches, matches_.size()), 171 std::min(AutocompleteProvider::kMaxMatches, matches_.size()),
167 matches_.end(), &AutocompleteMatch::MoreRelevant); 172 matches_.end(), &AutocompleteMatch::MoreRelevant);
168 if (matches_.size() > AutocompleteProvider::kMaxMatches) { 173 if (matches_.size() > AutocompleteProvider::kMaxMatches) {
169 matches_.erase(matches_.begin() + AutocompleteProvider::kMaxMatches, 174 matches_.erase(matches_.begin() + AutocompleteProvider::kMaxMatches,
170 matches_.end()); 175 matches_.end());
171 } 176 }
177 // Reset relevance scores to guarantee no results are given an
178 // inlineable score and all scores are decreasing (but not do assign
179 // any scores below 1).
180 int max_relevance = AutocompleteResult::kLowestDefaultScore - 1;
181 for (ACMatches::iterator it = matches_.begin(); it != matches_.end(); ++it) {
182 max_relevance = std::min(max_relevance, it->relevance);
183 it->relevance = max_relevance;
184 if (max_relevance > 1)
185 max_relevance--;
Peter Kasting 2013/06/20 00:06:28 Tiny nit: Use preincrement wherever you don't need
Mark P 2013/06/20 00:23:16 Done.
186 }
172 } 187 }
173 188
174 AutocompleteMatch ShortcutsProvider::ShortcutToACMatch( 189 AutocompleteMatch ShortcutsProvider::ShortcutToACMatch(
175 int relevance, 190 int relevance,
176 const string16& term_string, 191 const string16& term_string,
177 const history::ShortcutsBackend::Shortcut& shortcut) { 192 const history::ShortcutsBackend::Shortcut& shortcut) {
178 DCHECK(!term_string.empty()); 193 DCHECK(!term_string.empty());
179 AutocompleteMatch match(this, relevance, true, 194 AutocompleteMatch match(this, relevance, true,
180 AutocompleteMatchType::HISTORY_TITLE); 195 AutocompleteMatchType::HISTORY_TITLE);
181 match.destination_url = shortcut.url; 196 match.destination_url = shortcut.url;
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
311 DCHECK(backend); 326 DCHECK(backend);
312 history::ShortcutsBackend::ShortcutMap::const_iterator it = 327 history::ShortcutsBackend::ShortcutMap::const_iterator it =
313 backend->shortcuts_map().lower_bound(keyword); 328 backend->shortcuts_map().lower_bound(keyword);
314 // Lower bound not necessarily matches the keyword, check for item pointed by 329 // Lower bound not necessarily matches the keyword, check for item pointed by
315 // the lower bound iterator to at least start with keyword. 330 // the lower bound iterator to at least start with keyword.
316 return ((it == backend->shortcuts_map().end()) || 331 return ((it == backend->shortcuts_map().end()) ||
317 StartsWith(it->first, keyword, true)) ? it : 332 StartsWith(it->first, keyword, true)) ? it :
318 backend->shortcuts_map().end(); 333 backend->shortcuts_map().end();
319 } 334 }
320 335
321 // static
322 int ShortcutsProvider::CalculateScore( 336 int ShortcutsProvider::CalculateScore(
323 const string16& terms, 337 const string16& terms,
324 const history::ShortcutsBackend::Shortcut& shortcut) { 338 const history::ShortcutsBackend::Shortcut& shortcut) {
325 DCHECK(!terms.empty()); 339 DCHECK(!terms.empty());
326 DCHECK_LE(terms.length(), shortcut.text.length()); 340 DCHECK_LE(terms.length(), shortcut.text.length());
327 341
328 // The initial score is based on how much of the shortcut the user has typed. 342 // The initial score is based on how much of the shortcut the user has typed.
329 // Using the square root of the typed fraction boosts the base score rapidly 343 // Using the square root of the typed fraction boosts the base score rapidly
330 // as characters are typed, compared with simply using the typed fraction 344 // as characters are typed, compared with simply using the typed fraction
331 // directly. This makes sense since the first characters typed are much more 345 // directly. This makes sense since the first characters typed are much more
332 // important for determining how likely it is a user wants a particular 346 // important for determining how likely it is a user wants a particular
333 // shortcut than are the remaining continued characters. 347 // shortcut than are the remaining continued characters.
334 double base_score = (AutocompleteResult::kLowestDefaultScore - 1) * 348 double base_score = max_relevance_ *
335 sqrt(static_cast<double>(terms.length()) / shortcut.text.length()); 349 sqrt(static_cast<double>(terms.length()) / shortcut.text.length());
336 350
337 // Then we decay this by half each week. 351 // Then we decay this by half each week.
338 const double kLn2 = 0.6931471805599453; 352 const double kLn2 = 0.6931471805599453;
339 base::TimeDelta time_passed = base::Time::Now() - shortcut.last_access_time; 353 base::TimeDelta time_passed = base::Time::Now() - shortcut.last_access_time;
340 // Clamp to 0 in case time jumps backwards (e.g. due to DST). 354 // Clamp to 0 in case time jumps backwards (e.g. due to DST).
341 double decay_exponent = std::max(0.0, kLn2 * static_cast<double>( 355 double decay_exponent = std::max(0.0, kLn2 * static_cast<double>(
342 time_passed.InMicroseconds()) / base::Time::kMicrosecondsPerWeek); 356 time_passed.InMicroseconds()) / base::Time::kMicrosecondsPerWeek);
343 357
344 // We modulate the decay factor based on how many times the shortcut has been 358 // We modulate the decay factor based on how many times the shortcut has been
345 // used. Newly created shortcuts decay at full speed; otherwise, decaying by 359 // used. Newly created shortcuts decay at full speed; otherwise, decaying by
346 // half takes |n| times as much time, where n increases by 360 // half takes |n| times as much time, where n increases by
347 // (1.0 / each 5 additional hits), up to a maximum of 5x as long. 361 // (1.0 / each 5 additional hits), up to a maximum of 5x as long.
348 const double kMaxDecaySpeedDivisor = 5.0; 362 const double kMaxDecaySpeedDivisor = 5.0;
349 const double kNumUsesPerDecaySpeedDivisorIncrement = 5.0; 363 const double kNumUsesPerDecaySpeedDivisorIncrement = 5.0;
350 double decay_divisor = std::min(kMaxDecaySpeedDivisor, 364 double decay_divisor = std::min(kMaxDecaySpeedDivisor,
351 (shortcut.number_of_hits + kNumUsesPerDecaySpeedDivisorIncrement - 1) / 365 (shortcut.number_of_hits + kNumUsesPerDecaySpeedDivisorIncrement - 1) /
352 kNumUsesPerDecaySpeedDivisorIncrement); 366 kNumUsesPerDecaySpeedDivisorIncrement);
353 367
354 return static_cast<int>((base_score / exp(decay_exponent / decay_divisor)) + 368 return static_cast<int>((base_score / exp(decay_exponent / decay_divisor)) +
355 0.5); 369 0.5);
356 } 370 }
OLDNEW
« no previous file with comments | « chrome/browser/autocomplete/shortcuts_provider.h ('k') | chrome/browser/omnibox/omnibox_field_trial.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698