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

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

Issue 200493006: Move the ShortcutsBackend from history to autocomplete so that it can fully (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 6 years, 9 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/time.h" 20 #include "base/time/time.h"
21 #include "chrome/browser/autocomplete/autocomplete_input.h" 21 #include "chrome/browser/autocomplete/autocomplete_input.h"
22 #include "chrome/browser/autocomplete/autocomplete_match.h" 22 #include "chrome/browser/autocomplete/autocomplete_match.h"
23 #include "chrome/browser/autocomplete/autocomplete_provider_listener.h" 23 #include "chrome/browser/autocomplete/autocomplete_provider_listener.h"
24 #include "chrome/browser/autocomplete/autocomplete_result.h" 24 #include "chrome/browser/autocomplete/autocomplete_result.h"
25 #include "chrome/browser/autocomplete/history_provider.h" 25 #include "chrome/browser/autocomplete/history_provider.h"
26 #include "chrome/browser/autocomplete/shortcuts_backend_factory.h"
26 #include "chrome/browser/autocomplete/url_prefix.h" 27 #include "chrome/browser/autocomplete/url_prefix.h"
27 #include "chrome/browser/history/history_notifications.h" 28 #include "chrome/browser/history/history_notifications.h"
28 #include "chrome/browser/history/history_service.h" 29 #include "chrome/browser/history/history_service.h"
29 #include "chrome/browser/history/history_service_factory.h" 30 #include "chrome/browser/history/history_service_factory.h"
30 #include "chrome/browser/history/shortcuts_backend_factory.h"
31 #include "chrome/browser/omnibox/omnibox_field_trial.h" 31 #include "chrome/browser/omnibox/omnibox_field_trial.h"
32 #include "chrome/browser/profiles/profile.h" 32 #include "chrome/browser/profiles/profile.h"
33 #include "chrome/common/net/url_fixer_upper.h" 33 #include "chrome/common/net/url_fixer_upper.h"
34 #include "chrome/common/pref_names.h" 34 #include "chrome/common/pref_names.h"
35 #include "chrome/common/url_constants.h" 35 #include "chrome/common/url_constants.h"
36 #include "url/url_parse.h" 36 #include "url/url_parse.h"
37 37
38 namespace { 38 namespace {
39 39
40 class DestinationURLEqualsURL { 40 class DestinationURLEqualsURL {
(...skipping 28 matching lines...) Expand all
69 } 69 }
70 70
71 } // namespace 71 } // namespace
72 72
73 ShortcutsProvider::ShortcutsProvider(AutocompleteProviderListener* listener, 73 ShortcutsProvider::ShortcutsProvider(AutocompleteProviderListener* listener,
74 Profile* profile) 74 Profile* profile)
75 : AutocompleteProvider(listener, profile, 75 : AutocompleteProvider(listener, profile,
76 AutocompleteProvider::TYPE_SHORTCUTS), 76 AutocompleteProvider::TYPE_SHORTCUTS),
77 languages_(profile_->GetPrefs()->GetString(prefs::kAcceptLanguages)), 77 languages_(profile_->GetPrefs()->GetString(prefs::kAcceptLanguages)),
78 initialized_(false) { 78 initialized_(false) {
79 scoped_refptr<history::ShortcutsBackend> backend = 79 scoped_refptr<ShortcutsBackend> backend =
80 ShortcutsBackendFactory::GetForProfile(profile_); 80 ShortcutsBackendFactory::GetForProfile(profile_);
81 if (backend.get()) { 81 if (backend.get()) {
82 backend->AddObserver(this); 82 backend->AddObserver(this);
83 if (backend->initialized()) 83 if (backend->initialized())
84 initialized_ = true; 84 initialized_ = true;
85 } 85 }
86 } 86 }
87 87
88 void ShortcutsProvider::Start(const AutocompleteInput& input, 88 void ShortcutsProvider::Start(const AutocompleteInput& input,
89 bool minimal_changes) { 89 bool minimal_changes) {
(...skipping 18 matching lines...) Expand all
108 base::HistogramBase* counter = base::Histogram::FactoryGet( 108 base::HistogramBase* counter = base::Histogram::FactoryGet(
109 name, 1, 1000, 50, base::Histogram::kUmaTargetedHistogramFlag); 109 name, 1, 1000, 50, base::Histogram::kUmaTargetedHistogramFlag);
110 counter->Add(static_cast<int>((end_time - start_time).InMilliseconds())); 110 counter->Add(static_cast<int>((end_time - start_time).InMilliseconds()));
111 } 111 }
112 UpdateStarredStateOfMatches(); 112 UpdateStarredStateOfMatches();
113 } 113 }
114 114
115 void ShortcutsProvider::DeleteMatch(const AutocompleteMatch& match) { 115 void ShortcutsProvider::DeleteMatch(const AutocompleteMatch& match) {
116 // Copy the URL since deleting from |matches_| will invalidate |match|. 116 // Copy the URL since deleting from |matches_| will invalidate |match|.
117 GURL url(match.destination_url); 117 GURL url(match.destination_url);
118 DCHECK(url.is_valid());
118 119
119 // When a user deletes a match, he probably means for the URL to disappear out 120 // When a user deletes a match, he probably means for the URL to disappear out
120 // of history entirely. So nuke all shortcuts that map to this URL. 121 // of history entirely. So nuke all shortcuts that map to this URL.
121 scoped_refptr<history::ShortcutsBackend> backend = 122 scoped_refptr<ShortcutsBackend> backend =
122 ShortcutsBackendFactory::GetForProfileIfExists(profile_); 123 ShortcutsBackendFactory::GetForProfileIfExists(profile_);
123 if (backend) // Can be NULL in Incognito. 124 if (backend) // Can be NULL in Incognito.
124 backend->DeleteShortcutsWithUrl(url); 125 backend->DeleteShortcutsWithURL(url);
125 126
126 matches_.erase(std::remove_if(matches_.begin(), matches_.end(), 127 matches_.erase(std::remove_if(matches_.begin(), matches_.end(),
127 DestinationURLEqualsURL(url)), 128 DestinationURLEqualsURL(url)),
128 matches_.end()); 129 matches_.end());
129 // NOTE: |match| is now dead! 130 // NOTE: |match| is now dead!
130 131
131 // Delete the match from the history DB. This will eventually result in a 132 // Delete the match from the history DB. This will eventually result in a
132 // second call to DeleteShortcutsWithURLs(), which is harmless. 133 // second call to DeleteShortcutsWithURL(), which is harmless.
133 HistoryService* const history_service = 134 HistoryService* const history_service =
134 HistoryServiceFactory::GetForProfile(profile_, Profile::EXPLICIT_ACCESS); 135 HistoryServiceFactory::GetForProfile(profile_, Profile::EXPLICIT_ACCESS);
135 136 DCHECK(history_service);
136 DCHECK(history_service && url.is_valid());
137 history_service->DeleteURL(url); 137 history_service->DeleteURL(url);
138 } 138 }
139 139
140 ShortcutsProvider::~ShortcutsProvider() { 140 ShortcutsProvider::~ShortcutsProvider() {
141 scoped_refptr<history::ShortcutsBackend> backend = 141 scoped_refptr<ShortcutsBackend> backend =
142 ShortcutsBackendFactory::GetForProfileIfExists(profile_); 142 ShortcutsBackendFactory::GetForProfileIfExists(profile_);
143 if (backend.get()) 143 if (backend.get())
144 backend->RemoveObserver(this); 144 backend->RemoveObserver(this);
145 } 145 }
146 146
147 void ShortcutsProvider::OnShortcutsLoaded() { 147 void ShortcutsProvider::OnShortcutsLoaded() {
148 initialized_ = true; 148 initialized_ = true;
149 } 149 }
150 150
151 void ShortcutsProvider::GetMatches(const AutocompleteInput& input) { 151 void ShortcutsProvider::GetMatches(const AutocompleteInput& input) {
152 scoped_refptr<history::ShortcutsBackend> backend = 152 scoped_refptr<ShortcutsBackend> backend =
153 ShortcutsBackendFactory::GetForProfileIfExists(profile_); 153 ShortcutsBackendFactory::GetForProfileIfExists(profile_);
154 if (!backend.get()) 154 if (!backend.get())
155 return; 155 return;
156 // Get the URLs from the shortcuts database with keys that partially or 156 // Get the URLs from the shortcuts database with keys that partially or
157 // completely match the search term. 157 // completely match the search term.
158 base::string16 term_string(base::i18n::ToLower(input.text())); 158 base::string16 term_string(base::i18n::ToLower(input.text()));
159 DCHECK(!term_string.empty()); 159 DCHECK(!term_string.empty());
160 160
161 base::string16 fixed_up_term_string(term_string); 161 base::string16 fixed_up_term_string(term_string);
162 AutocompleteInput fixed_up_input(input); 162 AutocompleteInput fixed_up_input(input);
163 if (FixupUserInput(&fixed_up_input)) 163 if (FixupUserInput(&fixed_up_input))
164 fixed_up_term_string = fixed_up_input.text(); 164 fixed_up_term_string = fixed_up_input.text();
165 165
166 int max_relevance; 166 int max_relevance;
167 if (!OmniboxFieldTrial::ShortcutsScoringMaxRelevance( 167 if (!OmniboxFieldTrial::ShortcutsScoringMaxRelevance(
168 input.current_page_classification(), &max_relevance)) 168 input.current_page_classification(), &max_relevance))
169 max_relevance = AutocompleteResult::kLowestDefaultScore - 1; 169 max_relevance = AutocompleteResult::kLowestDefaultScore - 1;
170 170
171 for (history::ShortcutsBackend::ShortcutMap::const_iterator it = 171 for (ShortcutsBackend::ShortcutMap::const_iterator it =
172 FindFirstMatch(term_string, backend.get()); 172 FindFirstMatch(term_string, backend.get());
173 it != backend->shortcuts_map().end() && 173 it != backend->shortcuts_map().end() &&
174 StartsWith(it->first, term_string, true); ++it) { 174 StartsWith(it->first, term_string, true); ++it) {
175 // Don't return shortcuts with zero relevance. 175 // Don't return shortcuts with zero relevance.
176 int relevance = CalculateScore(term_string, it->second, max_relevance); 176 int relevance = CalculateScore(term_string, it->second, max_relevance);
177 if (relevance) { 177 if (relevance) {
178 matches_.push_back(ShortcutToACMatch( 178 matches_.push_back(ShortcutToACMatch(
179 it->second, relevance, term_string, fixed_up_term_string, 179 it->second, relevance, term_string, fixed_up_term_string,
180 input.prevent_inline_autocomplete())); 180 input.prevent_inline_autocomplete()));
181 matches_.back().ComputeStrippedDestinationURL(profile_); 181 matches_.back().ComputeStrippedDestinationURL(profile_);
(...skipping 28 matching lines...) Expand all
210 } 210 }
211 for (ACMatches::iterator it = matches_.begin(); it != matches_.end(); ++it) { 211 for (ACMatches::iterator it = matches_.begin(); it != matches_.end(); ++it) {
212 max_relevance = std::min(max_relevance, it->relevance); 212 max_relevance = std::min(max_relevance, it->relevance);
213 it->relevance = max_relevance; 213 it->relevance = max_relevance;
214 if (max_relevance > 1) 214 if (max_relevance > 1)
215 --max_relevance; 215 --max_relevance;
216 } 216 }
217 } 217 }
218 218
219 AutocompleteMatch ShortcutsProvider::ShortcutToACMatch( 219 AutocompleteMatch ShortcutsProvider::ShortcutToACMatch(
220 const history::ShortcutsBackend::Shortcut& shortcut, 220 const history::ShortcutsDatabase::Shortcut& shortcut,
221 int relevance, 221 int relevance,
222 const base::string16& term_string, 222 const base::string16& term_string,
223 const base::string16& fixed_up_term_string, 223 const base::string16& fixed_up_term_string,
224 const bool prevent_inline_autocomplete) { 224 const bool prevent_inline_autocomplete) {
225 DCHECK(!term_string.empty()); 225 DCHECK(!term_string.empty());
226 AutocompleteMatch match(shortcut.match_core.ToMatch()); 226 AutocompleteMatch match;
227 match.provider = this; 227 match.provider = this;
228 match.relevance = relevance; 228 match.relevance = relevance;
229 match.deletable = true; 229 match.deletable = true;
230 match.fill_into_edit = shortcut.match_core.fill_into_edit;
231 match.destination_url = shortcut.match_core.destination_url;
230 DCHECK(match.destination_url.is_valid()); 232 DCHECK(match.destination_url.is_valid());
233 match.contents = shortcut.match_core.contents;
234 match.contents_class = AutocompleteMatch::ClassificationsFromString(
235 shortcut.match_core.contents_class);
236 match.description = shortcut.match_core.description;
237 match.description_class = AutocompleteMatch::ClassificationsFromString(
238 shortcut.match_core.description_class);
239 match.transition =
240 static_cast<content::PageTransition>(shortcut.match_core.transition);
241 match.type = static_cast<AutocompleteMatch::Type>(shortcut.match_core.type);
242 match.keyword = shortcut.match_core.keyword;
231 match.RecordAdditionalInfo("number of hits", shortcut.number_of_hits); 243 match.RecordAdditionalInfo("number of hits", shortcut.number_of_hits);
232 match.RecordAdditionalInfo("last access time", shortcut.last_access_time); 244 match.RecordAdditionalInfo("last access time", shortcut.last_access_time);
233 match.RecordAdditionalInfo("original input text", 245 match.RecordAdditionalInfo("original input text",
234 base::UTF16ToUTF8(shortcut.text)); 246 base::UTF16ToUTF8(shortcut.text));
235 247
236 // Set |inline_autocompletion| and |allowed_to_be_default_match| if possible. 248 // Set |inline_autocompletion| and |allowed_to_be_default_match| if possible.
237 // If the match is a search query this is easy: simply check whether the 249 // If the match is a search query this is easy: simply check whether the
238 // user text is a prefix of the query. If the match is a navigation, we 250 // user text is a prefix of the query. If the match is a navigation, we
239 // assume the fill_into_edit looks something like a URL, so we use 251 // assume the fill_into_edit looks something like a URL, so we use
240 // BestURLPrefix() to try and strip off any prefixes that the user might 252 // BestURLPrefix() to try and strip off any prefixes that the user might
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
382 last_position = word_end; 394 last_position = word_end;
383 break; 395 break;
384 } 396 }
385 } 397 }
386 last_position = std::max(last_position, next_character); 398 last_position = std::max(last_position, next_character);
387 } 399 }
388 400
389 return AutocompleteMatch::MergeClassifications(original_class, match_class); 401 return AutocompleteMatch::MergeClassifications(original_class, match_class);
390 } 402 }
391 403
392 history::ShortcutsBackend::ShortcutMap::const_iterator 404 ShortcutsBackend::ShortcutMap::const_iterator
393 ShortcutsProvider::FindFirstMatch(const base::string16& keyword, 405 ShortcutsProvider::FindFirstMatch(const base::string16& keyword,
394 history::ShortcutsBackend* backend) { 406 ShortcutsBackend* backend) {
395 DCHECK(backend); 407 DCHECK(backend);
396 history::ShortcutsBackend::ShortcutMap::const_iterator it = 408 ShortcutsBackend::ShortcutMap::const_iterator it =
397 backend->shortcuts_map().lower_bound(keyword); 409 backend->shortcuts_map().lower_bound(keyword);
398 // Lower bound not necessarily matches the keyword, check for item pointed by 410 // Lower bound not necessarily matches the keyword, check for item pointed by
399 // the lower bound iterator to at least start with keyword. 411 // the lower bound iterator to at least start with keyword.
400 return ((it == backend->shortcuts_map().end()) || 412 return ((it == backend->shortcuts_map().end()) ||
401 StartsWith(it->first, keyword, true)) ? it : 413 StartsWith(it->first, keyword, true)) ? it :
402 backend->shortcuts_map().end(); 414 backend->shortcuts_map().end();
403 } 415 }
404 416
405 int ShortcutsProvider::CalculateScore( 417 int ShortcutsProvider::CalculateScore(
406 const base::string16& terms, 418 const base::string16& terms,
407 const history::ShortcutsBackend::Shortcut& shortcut, 419 const history::ShortcutsDatabase::Shortcut& shortcut,
408 int max_relevance) { 420 int max_relevance) {
409 DCHECK(!terms.empty()); 421 DCHECK(!terms.empty());
410 DCHECK_LE(terms.length(), shortcut.text.length()); 422 DCHECK_LE(terms.length(), shortcut.text.length());
411 423
412 // The initial score is based on how much of the shortcut the user has typed. 424 // The initial score is based on how much of the shortcut the user has typed.
413 // Using the square root of the typed fraction boosts the base score rapidly 425 // Using the square root of the typed fraction boosts the base score rapidly
414 // as characters are typed, compared with simply using the typed fraction 426 // as characters are typed, compared with simply using the typed fraction
415 // directly. This makes sense since the first characters typed are much more 427 // directly. This makes sense since the first characters typed are much more
416 // important for determining how likely it is a user wants a particular 428 // important for determining how likely it is a user wants a particular
417 // shortcut than are the remaining continued characters. 429 // shortcut than are the remaining continued characters.
(...skipping 13 matching lines...) Expand all
431 // (1.0 / each 5 additional hits), up to a maximum of 5x as long. 443 // (1.0 / each 5 additional hits), up to a maximum of 5x as long.
432 const double kMaxDecaySpeedDivisor = 5.0; 444 const double kMaxDecaySpeedDivisor = 5.0;
433 const double kNumUsesPerDecaySpeedDivisorIncrement = 5.0; 445 const double kNumUsesPerDecaySpeedDivisorIncrement = 5.0;
434 double decay_divisor = std::min(kMaxDecaySpeedDivisor, 446 double decay_divisor = std::min(kMaxDecaySpeedDivisor,
435 (shortcut.number_of_hits + kNumUsesPerDecaySpeedDivisorIncrement - 1) / 447 (shortcut.number_of_hits + kNumUsesPerDecaySpeedDivisorIncrement - 1) /
436 kNumUsesPerDecaySpeedDivisorIncrement); 448 kNumUsesPerDecaySpeedDivisorIncrement);
437 449
438 return static_cast<int>((base_score / exp(decay_exponent / decay_divisor)) + 450 return static_cast<int>((base_score / exp(decay_exponent / decay_divisor)) +
439 0.5); 451 0.5);
440 } 452 }
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