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

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

Issue 7607007: Add confidence to AutocompleteMatch. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase Created 9 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) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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/history_contents_provider.h" 5 #include "chrome/browser/autocomplete/history_contents_provider.h"
6 6
7 #include "base/callback.h" 7 #include "base/callback.h"
8 #include "base/metrics/histogram.h" 8 #include "base/metrics/histogram.h"
9 #include "base/string_util.h" 9 #include "base/string_util.h"
10 #include "base/utf_string_conversions.h" 10 #include "base/utf_string_conversions.h"
11 #include "chrome/browser/autocomplete/autocomplete_match.h" 11 #include "chrome/browser/autocomplete/autocomplete_match.h"
12 #include "chrome/browser/bookmarks/bookmark_model.h" 12 #include "chrome/browser/bookmarks/bookmark_model.h"
13 #include "chrome/browser/bookmarks/bookmark_utils.h" 13 #include "chrome/browser/bookmarks/bookmark_utils.h"
14 #include "chrome/browser/profiles/profile.h" 14 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/common/url_constants.h" 15 #include "chrome/common/url_constants.h"
16 #include "googleurl/src/url_util.h" 16 #include "googleurl/src/url_util.h"
17 #include "net/base/net_util.h" 17 #include "net/base/net_util.h"
18 18
19 using base::TimeTicks; 19 using base::TimeTicks;
20 using history::HistoryDatabase;
20 21
21 namespace { 22 namespace {
22 23
23 // Number of days to search for full text results. The longer this is, the more 24 // Number of days to search for full text results. The longer this is, the more
24 // time it will take. 25 // time it will take.
25 const int kDaysToSearch = 30; 26 const int kDaysToSearch = 30;
26 27
27 // When processing the results from the history query, this structure points to 28 } // end namespace
28 // a single result. It allows the results to be sorted and processed without
29 // modifying the larger and slower results structure.
30 struct MatchReference {
31 MatchReference(const history::URLResult* result, int relevance)
32 : result(result),
33 relevance(relevance) {
34 }
35 29
36 const history::URLResult* result; 30 HistoryContentsProvider::MatchReference::MatchReference(
37 int relevance; // Score of relevance computed by CalculateRelevance. 31 const history::URLResult* result,
38 }; 32 int relevance,
39 33 float confidence)
40 // This is a > operator for MatchReference. 34 : result(result),
41 bool CompareMatchRelevance(const MatchReference& a, const MatchReference& b) { 35 relevance(relevance),
42 if (a.relevance != b.relevance) 36 confidence(confidence) {
43 return a.relevance > b.relevance;
44
45 // Want results in reverse-chronological order all else being equal.
46 return a.result->last_visit() > b.result->last_visit();
47 } 37 }
48 38
49 } // namespace 39 // static
50 40 bool HistoryContentsProvider::MatchReference::CompareRelevance(
51 using history::HistoryDatabase; 41 const HistoryContentsProvider::MatchReference& lhs,
42 const HistoryContentsProvider::MatchReference& rhs) {
43 if (lhs.relevance != rhs.relevance)
44 return lhs.relevance > rhs.relevance;
45 return lhs.result->last_visit() > rhs.result->last_visit();
46 }
52 47
53 HistoryContentsProvider::HistoryContentsProvider(ACProviderListener* listener, 48 HistoryContentsProvider::HistoryContentsProvider(ACProviderListener* listener,
54 Profile* profile, 49 Profile* profile,
55 bool body_only) 50 bool body_only)
56 : HistoryProvider(listener, profile, "HistoryContents"), 51 : HistoryProvider(listener, profile, "HistoryContents"),
57 star_title_count_(0), 52 star_title_count_(0),
58 star_contents_count_(0), 53 star_contents_count_(0),
59 title_count_(0), 54 title_count_(0),
60 contents_count_(0), 55 contents_count_(0),
61 input_type_(AutocompleteInput::INVALID), 56 input_type_(AutocompleteInput::INVALID),
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
180 175
181 // Make the result references and score the results. 176 // Make the result references and score the results.
182 std::vector<MatchReference> result_refs; 177 std::vector<MatchReference> result_refs;
183 result_refs.reserve(results_.size()); 178 result_refs.reserve(results_.size());
184 179
185 // Results are sorted in decreasing order so we run the loop backwards so that 180 // Results are sorted in decreasing order so we run the loop backwards so that
186 // the relevance increment favors the higher ranked results. 181 // the relevance increment favors the higher ranked results.
187 for (std::vector<history::URLResult*>::const_reverse_iterator i = 182 for (std::vector<history::URLResult*>::const_reverse_iterator i =
188 results_.rbegin(); i != results_.rend(); ++i) { 183 results_.rbegin(); i != results_.rend(); ++i) {
189 history::URLResult* result = *i; 184 history::URLResult* result = *i;
190 MatchReference ref(result, CalculateRelevance(*result)); 185 MatchReference ref(result, CalculateRelevance(*result),
186 CalculateConfidence(*result, results_));
191 result_refs.push_back(ref); 187 result_refs.push_back(ref);
192 } 188 }
193 189
194 // Get the top matches and add them. 190 // Get the top matches and add them.
195 size_t max_for_provider = std::min(kMaxMatches, result_refs.size()); 191 size_t max_for_provider = std::min(kMaxMatches, result_refs.size());
196 std::partial_sort(result_refs.begin(), result_refs.begin() + max_for_provider, 192 std::partial_sort(result_refs.begin(), result_refs.begin() + max_for_provider,
197 result_refs.end(), &CompareMatchRelevance); 193 result_refs.end(), &MatchReference::CompareRelevance);
198 matches_.clear(); 194 matches_.clear();
199 for (size_t i = 0; i < max_for_provider; i++) { 195 for (size_t i = 0; i < max_for_provider; i++) {
200 matches_.push_back(ResultToMatch(*result_refs[i].result, 196 AutocompleteMatch match(ResultToMatch(result_refs[i]));
201 result_refs[i].relevance)); 197 UMA_HISTOGRAM_COUNTS_100("Autocomplete.Confidence_HistoryContents",
198 match.confidence * 100);
199 matches_.push_back(match);
202 } 200 }
203 } 201 }
204 202
205 // TODO(mrossetti): Remove MatchInTitle once body_only_ becomes permanent. 203 // TODO(mrossetti): Remove MatchInTitle once body_only_ becomes permanent.
206 bool HistoryContentsProvider::MatchInTitle(const history::URLResult& result) { 204 bool HistoryContentsProvider::MatchInTitle(const history::URLResult& result) {
207 return !body_only_ && !result.title_match_positions().empty(); 205 return !body_only_ && !result.title_match_positions().empty();
208 } 206 }
209 207
210 AutocompleteMatch HistoryContentsProvider::ResultToMatch( 208 AutocompleteMatch HistoryContentsProvider::ResultToMatch(
211 const history::URLResult& result, 209 const MatchReference& match_reference) {
212 int score) { 210 const history::URLResult& result = *match_reference.result;
213 AutocompleteMatch match(this, score, true, MatchInTitle(result) ? 211 AutocompleteMatch match(this, match_reference.relevance,
214 AutocompleteMatch::HISTORY_TITLE : AutocompleteMatch::HISTORY_BODY); 212 match_reference.confidence, true, MatchInTitle(result) ?
213 AutocompleteMatch::HISTORY_TITLE : AutocompleteMatch::HISTORY_BODY);
215 match.contents = StringForURLDisplay(result.url(), true, trim_http_); 214 match.contents = StringForURLDisplay(result.url(), true, trim_http_);
216 match.fill_into_edit = 215 match.fill_into_edit =
217 AutocompleteInput::FormattedStringWithEquivalentMeaning(result.url(), 216 AutocompleteInput::FormattedStringWithEquivalentMeaning(result.url(),
218 match.contents); 217 match.contents);
219 match.destination_url = result.url(); 218 match.destination_url = result.url();
220 match.contents_class.push_back( 219 match.contents_class.push_back(
221 ACMatchClassification(0, ACMatchClassification::URL)); 220 ACMatchClassification(0, ACMatchClassification::URL));
222 match.description = result.title(); 221 match.description = result.title();
223 match.starred = 222 match.starred =
224 (profile_->GetBookmarkModel() && 223 (profile_->GetBookmarkModel() &&
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
256 int HistoryContentsProvider::CalculateRelevance( 255 int HistoryContentsProvider::CalculateRelevance(
257 const history::URLResult& result) { 256 const history::URLResult& result) {
258 const bool in_title = MatchInTitle(result); 257 const bool in_title = MatchInTitle(result);
259 if (!profile_->GetBookmarkModel() || 258 if (!profile_->GetBookmarkModel() ||
260 !profile_->GetBookmarkModel()->IsBookmarked(result.url())) 259 !profile_->GetBookmarkModel()->IsBookmarked(result.url()))
261 return in_title ? (700 + title_count_++) : (500 + contents_count_++); 260 return in_title ? (700 + title_count_++) : (500 + contents_count_++);
262 return in_title ? 261 return in_title ?
263 (1000 + star_title_count_++) : (550 + star_contents_count_++); 262 (1000 + star_title_count_++) : (550 + star_contents_count_++);
264 } 263 }
265 264
265 float HistoryContentsProvider::CalculateConfidence(
266 const history::URLResult& result,
267 const history::QueryResults& results) const {
268 // Calculate a score of [0, 0.9] based on typed count.
269 // Using typed count in place of visit count as:
270 // - It's a better indicator of what the user wants to open given that they
271 // are typing in the address bar (users tend to open certain URLs by typing
272 // and others by e.g. bookmarks, so visit_count is a good indicator of
273 // overall interest but a bad one for specifically omnibox interest).
274 // - Since the DB query is sorted by typed_count, the results may be
275 // effectively a random selection as far as visit_counts are concerned
276 // (meaning many high-visit_count-URLs may be present in one query and
277 // absent in a similar one), leading to wild swings in confidence for the
278 // same result across distinct queries.
279 float numerator = result.typed_count();
280 float denominator = 0.0f;
281 for (std::vector<history::URLResult*>::const_iterator it = results.begin();
282 it != results.end(); ++it) {
283 denominator += (*it)->typed_count();
284 }
285 // It should only be equal to 0 if the result is not in the results vector.
286 if (denominator < 1) {
287 numerator = result.visit_count();
288 for (std::vector<history::URLResult*>::const_iterator it = results.begin();
289 it != results.end(); ++it) {
290 denominator += (*it)->visit_count();
291 }
292 }
293
294 float score = 0.9f * (denominator > 0.0f ? numerator / denominator : 0);
295
296 // Add 0.1 if the URL is bookmarked to get a final range of [0, 1].
297 if (profile_->GetBookmarkModel() &&
298 profile_->GetBookmarkModel()->IsBookmarked(result.url())) {
299 score += 0.1f;
300 }
301
302 return score;
303 }
304
266 void HistoryContentsProvider::QueryBookmarks(const AutocompleteInput& input) { 305 void HistoryContentsProvider::QueryBookmarks(const AutocompleteInput& input) {
267 BookmarkModel* bookmark_model = profile_->GetBookmarkModel(); 306 BookmarkModel* bookmark_model = profile_->GetBookmarkModel();
268 if (!bookmark_model) 307 if (!bookmark_model)
269 return; 308 return;
270 309
271 DCHECK(results_.empty()); 310 DCHECK(results_.empty());
272 311
273 TimeTicks start_time = TimeTicks::Now(); 312 TimeTicks start_time = TimeTicks::Now();
274 std::vector<bookmark_utils::TitleMatch> matches; 313 std::vector<bookmark_utils::TitleMatch> matches;
275 bookmark_model->GetBookmarksWithTitlesMatching(input.text(), 314 bookmark_model->GetBookmarksWithTitlesMatching(input.text(),
276 kMaxMatches, &matches); 315 kMaxMatches, &matches);
277 for (size_t i = 0; i < matches.size(); ++i) 316 for (size_t i = 0; i < matches.size(); ++i)
278 AddBookmarkTitleMatchToResults(matches[i]); 317 AddBookmarkTitleMatchToResults(matches[i]);
279 UMA_HISTOGRAM_TIMES("Omnibox.QueryBookmarksTime", 318 UMA_HISTOGRAM_TIMES("Omnibox.QueryBookmarksTime",
280 TimeTicks::Now() - start_time); 319 TimeTicks::Now() - start_time);
281 } 320 }
282 321
283 void HistoryContentsProvider::AddBookmarkTitleMatchToResults( 322 void HistoryContentsProvider::AddBookmarkTitleMatchToResults(
284 const bookmark_utils::TitleMatch& match) { 323 const bookmark_utils::TitleMatch& match) {
285 history::URLResult url_result(match.node->url(), match.match_positions); 324 history::URLResult url_result(match.node->url(), match.match_positions);
286 url_result.set_title(match.node->GetTitle()); 325 url_result.set_title(match.node->GetTitle());
287 results_.AppendURLBySwapping(&url_result); 326 results_.AppendURLBySwapping(&url_result);
288 } 327 }
OLDNEW
« no previous file with comments | « chrome/browser/autocomplete/history_contents_provider.h ('k') | chrome/browser/autocomplete/history_quick_provider.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698