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

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

Issue 22354006: Omnibox: Convert Shortcuts Scoring Field Trial to Omnibox Bundled Field Trial (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 4 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 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
47 const std::set<GURL>& urls_; 47 const std::set<GURL>& urls_;
48 }; 48 };
49 49
50 } // namespace 50 } // namespace
51 51
52 ShortcutsProvider::ShortcutsProvider(AutocompleteProviderListener* listener, 52 ShortcutsProvider::ShortcutsProvider(AutocompleteProviderListener* listener,
53 Profile* profile) 53 Profile* profile)
54 : AutocompleteProvider(listener, profile, 54 : AutocompleteProvider(listener, profile,
55 AutocompleteProvider::TYPE_SHORTCUTS), 55 AutocompleteProvider::TYPE_SHORTCUTS),
56 languages_(profile_->GetPrefs()->GetString(prefs::kAcceptLanguages)), 56 languages_(profile_->GetPrefs()->GetString(prefs::kAcceptLanguages)),
57 initialized_(false), 57 initialized_(false) {
58 max_relevance_(AutocompleteResult::kLowestDefaultScore - 1) {
59 scoped_refptr<history::ShortcutsBackend> backend = 58 scoped_refptr<history::ShortcutsBackend> backend =
60 ShortcutsBackendFactory::GetForProfile(profile_); 59 ShortcutsBackendFactory::GetForProfile(profile_);
61 if (backend.get()) { 60 if (backend.get()) {
62 backend->AddObserver(this); 61 backend->AddObserver(this);
63 if (backend->initialized()) 62 if (backend->initialized())
64 initialized_ = true; 63 initialized_ = true;
65 } 64 }
66 int max_relevance;
67 if (OmniboxFieldTrial::ShortcutsScoringMaxRelevance(&max_relevance))
68 max_relevance_ = max_relevance;
69 } 65 }
70 66
71 void ShortcutsProvider::Start(const AutocompleteInput& input, 67 void ShortcutsProvider::Start(const AutocompleteInput& input,
72 bool minimal_changes) { 68 bool minimal_changes) {
73 matches_.clear(); 69 matches_.clear();
74 70
75 if ((input.type() == AutocompleteInput::INVALID) || 71 if ((input.type() == AutocompleteInput::INVALID) ||
76 (input.type() == AutocompleteInput::FORCED_QUERY)) 72 (input.type() == AutocompleteInput::FORCED_QUERY))
77 return; 73 return;
78 74
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
150 void ShortcutsProvider::GetMatches(const AutocompleteInput& input) { 146 void ShortcutsProvider::GetMatches(const AutocompleteInput& input) {
151 scoped_refptr<history::ShortcutsBackend> backend = 147 scoped_refptr<history::ShortcutsBackend> backend =
152 ShortcutsBackendFactory::GetForProfileIfExists(profile_); 148 ShortcutsBackendFactory::GetForProfileIfExists(profile_);
153 if (!backend.get()) 149 if (!backend.get())
154 return; 150 return;
155 // Get the URLs from the shortcuts database with keys that partially or 151 // Get the URLs from the shortcuts database with keys that partially or
156 // completely match the search term. 152 // completely match the search term.
157 string16 term_string(base::i18n::ToLower(input.text())); 153 string16 term_string(base::i18n::ToLower(input.text()));
158 DCHECK(!term_string.empty()); 154 DCHECK(!term_string.empty());
159 155
156 int max_relevance;
157 if (!OmniboxFieldTrial::ShortcutsScoringMaxRelevance(
Peter Kasting 2013/08/09 23:33:15 Nit: Perhaps we should default-initialize the temp
Mark P 2013/08/10 00:11:56 I prefer this type of structure (success_bool, var
158 input.current_page_classification(), &max_relevance))
159 max_relevance = AutocompleteResult::kLowestDefaultScore - 1;
160
160 for (history::ShortcutsBackend::ShortcutMap::const_iterator it = 161 for (history::ShortcutsBackend::ShortcutMap::const_iterator it =
161 FindFirstMatch(term_string, backend.get()); 162 FindFirstMatch(term_string, backend.get());
162 it != backend->shortcuts_map().end() && 163 it != backend->shortcuts_map().end() &&
163 StartsWith(it->first, term_string, true); ++it) { 164 StartsWith(it->first, term_string, true); ++it) {
164 // Don't return shortcuts with zero relevance. 165 // Don't return shortcuts with zero relevance.
165 int relevance = CalculateScore(term_string, it->second); 166 int relevance = CalculateScore(term_string, it->second, max_relevance);
166 if (relevance) 167 if (relevance)
167 matches_.push_back(ShortcutToACMatch(relevance, term_string, it->second)); 168 matches_.push_back(ShortcutToACMatch(relevance, term_string, it->second));
168 } 169 }
169 std::partial_sort(matches_.begin(), 170 std::partial_sort(matches_.begin(),
170 matches_.begin() + 171 matches_.begin() +
171 std::min(AutocompleteProvider::kMaxMatches, matches_.size()), 172 std::min(AutocompleteProvider::kMaxMatches, matches_.size()),
172 matches_.end(), &AutocompleteMatch::MoreRelevant); 173 matches_.end(), &AutocompleteMatch::MoreRelevant);
173 if (matches_.size() > AutocompleteProvider::kMaxMatches) { 174 if (matches_.size() > AutocompleteProvider::kMaxMatches) {
174 matches_.erase(matches_.begin() + AutocompleteProvider::kMaxMatches, 175 matches_.erase(matches_.begin() + AutocompleteProvider::kMaxMatches,
175 matches_.end()); 176 matches_.end());
176 } 177 }
177 // Reset relevance scores to guarantee no results are given an 178 // Reset relevance scores to guarantee no results are given an
178 // inlineable score and all scores are decreasing (but not do assign 179 // inlineable score and all scores are decreasing (but not do assign
179 // any scores below 1). 180 // any scores below 1).
180 int max_relevance = AutocompleteResult::kLowestDefaultScore - 1; 181 max_relevance = AutocompleteResult::kLowestDefaultScore - 1;
181 for (ACMatches::iterator it = matches_.begin(); it != matches_.end(); ++it) { 182 for (ACMatches::iterator it = matches_.begin(); it != matches_.end(); ++it) {
182 max_relevance = std::min(max_relevance, it->relevance); 183 max_relevance = std::min(max_relevance, it->relevance);
183 it->relevance = max_relevance; 184 it->relevance = max_relevance;
184 if (max_relevance > 1) 185 if (max_relevance > 1)
185 --max_relevance; 186 --max_relevance;
186 } 187 }
187 } 188 }
188 189
189 AutocompleteMatch ShortcutsProvider::ShortcutToACMatch( 190 AutocompleteMatch ShortcutsProvider::ShortcutToACMatch(
190 int relevance, 191 int relevance,
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
331 backend->shortcuts_map().lower_bound(keyword); 332 backend->shortcuts_map().lower_bound(keyword);
332 // Lower bound not necessarily matches the keyword, check for item pointed by 333 // Lower bound not necessarily matches the keyword, check for item pointed by
333 // the lower bound iterator to at least start with keyword. 334 // the lower bound iterator to at least start with keyword.
334 return ((it == backend->shortcuts_map().end()) || 335 return ((it == backend->shortcuts_map().end()) ||
335 StartsWith(it->first, keyword, true)) ? it : 336 StartsWith(it->first, keyword, true)) ? it :
336 backend->shortcuts_map().end(); 337 backend->shortcuts_map().end();
337 } 338 }
338 339
339 int ShortcutsProvider::CalculateScore( 340 int ShortcutsProvider::CalculateScore(
340 const string16& terms, 341 const string16& terms,
341 const history::ShortcutsBackend::Shortcut& shortcut) { 342 const history::ShortcutsBackend::Shortcut& shortcut,
343 int max_relevance) {
342 DCHECK(!terms.empty()); 344 DCHECK(!terms.empty());
343 DCHECK_LE(terms.length(), shortcut.text.length()); 345 DCHECK_LE(terms.length(), shortcut.text.length());
344 346
345 // The initial score is based on how much of the shortcut the user has typed. 347 // The initial score is based on how much of the shortcut the user has typed.
346 // Using the square root of the typed fraction boosts the base score rapidly 348 // Using the square root of the typed fraction boosts the base score rapidly
347 // as characters are typed, compared with simply using the typed fraction 349 // as characters are typed, compared with simply using the typed fraction
348 // directly. This makes sense since the first characters typed are much more 350 // directly. This makes sense since the first characters typed are much more
349 // important for determining how likely it is a user wants a particular 351 // important for determining how likely it is a user wants a particular
350 // shortcut than are the remaining continued characters. 352 // shortcut than are the remaining continued characters.
351 double base_score = max_relevance_ * 353 double base_score = max_relevance *
352 sqrt(static_cast<double>(terms.length()) / shortcut.text.length()); 354 sqrt(static_cast<double>(terms.length()) / shortcut.text.length());
353 355
354 // Then we decay this by half each week. 356 // Then we decay this by half each week.
355 const double kLn2 = 0.6931471805599453; 357 const double kLn2 = 0.6931471805599453;
356 base::TimeDelta time_passed = base::Time::Now() - shortcut.last_access_time; 358 base::TimeDelta time_passed = base::Time::Now() - shortcut.last_access_time;
357 // Clamp to 0 in case time jumps backwards (e.g. due to DST). 359 // Clamp to 0 in case time jumps backwards (e.g. due to DST).
358 double decay_exponent = std::max(0.0, kLn2 * static_cast<double>( 360 double decay_exponent = std::max(0.0, kLn2 * static_cast<double>(
359 time_passed.InMicroseconds()) / base::Time::kMicrosecondsPerWeek); 361 time_passed.InMicroseconds()) / base::Time::kMicrosecondsPerWeek);
360 362
361 // We modulate the decay factor based on how many times the shortcut has been 363 // We modulate the decay factor based on how many times the shortcut has been
362 // used. Newly created shortcuts decay at full speed; otherwise, decaying by 364 // used. Newly created shortcuts decay at full speed; otherwise, decaying by
363 // half takes |n| times as much time, where n increases by 365 // half takes |n| times as much time, where n increases by
364 // (1.0 / each 5 additional hits), up to a maximum of 5x as long. 366 // (1.0 / each 5 additional hits), up to a maximum of 5x as long.
365 const double kMaxDecaySpeedDivisor = 5.0; 367 const double kMaxDecaySpeedDivisor = 5.0;
366 const double kNumUsesPerDecaySpeedDivisorIncrement = 5.0; 368 const double kNumUsesPerDecaySpeedDivisorIncrement = 5.0;
367 double decay_divisor = std::min(kMaxDecaySpeedDivisor, 369 double decay_divisor = std::min(kMaxDecaySpeedDivisor,
368 (shortcut.number_of_hits + kNumUsesPerDecaySpeedDivisorIncrement - 1) / 370 (shortcut.number_of_hits + kNumUsesPerDecaySpeedDivisorIncrement - 1) /
369 kNumUsesPerDecaySpeedDivisorIncrement); 371 kNumUsesPerDecaySpeedDivisorIncrement);
370 372
371 return static_cast<int>((base_score / exp(decay_exponent / decay_divisor)) + 373 return static_cast<int>((base_score / exp(decay_exponent / decay_divisor)) +
372 0.5); 374 0.5);
373 } 375 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698