Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 | 20 |
| 21 namespace { | 21 namespace { |
| 22 | 22 |
| 23 // Number of days to search for full text results. The longer this is, the more | 23 // Number of days to search for full text results. The longer this is, the more |
| 24 // time it will take. | 24 // time it will take. |
| 25 const int kDaysToSearch = 30; | 25 const int kDaysToSearch = 30; |
| 26 | 26 |
| 27 } // end namespace | |
| 28 | |
| 27 // When processing the results from the history query, this structure points to | 29 // When processing the results from the history query, this structure points to |
| 28 // a single result. It allows the results to be sorted and processed without | 30 // a single result. It allows the results to be sorted and processed without |
| 29 // modifying the larger and slower results structure. | 31 // modifying the larger and slower results structure. |
| 30 struct MatchReference { | 32 struct MatchReference { |
| 31 MatchReference(const history::URLResult* result, int relevance) | 33 MatchReference(const history::URLResult* result, |
| 34 int relevance, | |
| 35 float confidence) | |
| 32 : result(result), | 36 : result(result), |
| 33 relevance(relevance) { | 37 relevance(relevance), |
| 38 confidence(confidence) { | |
| 34 } | 39 } |
| 35 | 40 |
| 36 const history::URLResult* result; | 41 const history::URLResult* result; |
| 37 int relevance; // Score of relevance computed by CalculateRelevance. | 42 int relevance; // Score of relevance computed by CalculateRelevance. |
| 43 float confidence; // Confidence computed by CalculateConfidence. | |
| 38 }; | 44 }; |
| 39 | 45 |
| 46 namespace { | |
|
Peter Kasting
2011/08/09 20:53:00
Nit: Don't split the anonymous namespace into two
dominich
2011/08/09 21:43:43
Done.
| |
| 47 | |
| 40 // This is a > operator for MatchReference. | 48 // This is a > operator for MatchReference. |
| 41 bool CompareMatchRelevance(const MatchReference& a, const MatchReference& b) { | 49 bool CompareMatchRelevance(const MatchReference& a, const MatchReference& b) { |
| 42 if (a.relevance != b.relevance) | 50 if (a.relevance != b.relevance) |
| 43 return a.relevance > b.relevance; | 51 return a.relevance > b.relevance; |
| 44 | 52 |
| 45 // Want results in reverse-chronological order all else being equal. | 53 // Want results in reverse-chronological order all else being equal. |
| 46 return a.result->last_visit() > b.result->last_visit(); | 54 return a.result->last_visit() > b.result->last_visit(); |
| 47 } | 55 } |
| 48 | 56 |
| 49 } // namespace | 57 } // end namespace |
| 50 | 58 |
| 51 using history::HistoryDatabase; | 59 using history::HistoryDatabase; |
| 52 | 60 |
| 53 HistoryContentsProvider::HistoryContentsProvider(ACProviderListener* listener, | 61 HistoryContentsProvider::HistoryContentsProvider(ACProviderListener* listener, |
| 54 Profile* profile, | 62 Profile* profile, |
| 55 bool body_only) | 63 bool body_only) |
| 56 : HistoryProvider(listener, profile, "HistoryContents"), | 64 : HistoryProvider(listener, profile, "HistoryContents"), |
| 57 star_title_count_(0), | 65 star_title_count_(0), |
| 58 star_contents_count_(0), | 66 star_contents_count_(0), |
| 59 title_count_(0), | 67 title_count_(0), |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 180 | 188 |
| 181 // Make the result references and score the results. | 189 // Make the result references and score the results. |
| 182 std::vector<MatchReference> result_refs; | 190 std::vector<MatchReference> result_refs; |
| 183 result_refs.reserve(results_.size()); | 191 result_refs.reserve(results_.size()); |
| 184 | 192 |
| 185 // Results are sorted in decreasing order so we run the loop backwards so that | 193 // Results are sorted in decreasing order so we run the loop backwards so that |
| 186 // the relevance increment favors the higher ranked results. | 194 // the relevance increment favors the higher ranked results. |
| 187 for (std::vector<history::URLResult*>::const_reverse_iterator i = | 195 for (std::vector<history::URLResult*>::const_reverse_iterator i = |
| 188 results_.rbegin(); i != results_.rend(); ++i) { | 196 results_.rbegin(); i != results_.rend(); ++i) { |
| 189 history::URLResult* result = *i; | 197 history::URLResult* result = *i; |
| 190 MatchReference ref(result, CalculateRelevance(*result)); | 198 MatchReference ref(result, CalculateRelevance(*result), |
| 199 CalculateConfidence(*result, results_)); | |
| 191 result_refs.push_back(ref); | 200 result_refs.push_back(ref); |
| 192 } | 201 } |
| 193 | 202 |
| 194 // Get the top matches and add them. | 203 // Get the top matches and add them. |
| 195 size_t max_for_provider = std::min(kMaxMatches, result_refs.size()); | 204 size_t max_for_provider = std::min(kMaxMatches, result_refs.size()); |
| 196 std::partial_sort(result_refs.begin(), result_refs.begin() + max_for_provider, | 205 std::partial_sort(result_refs.begin(), result_refs.begin() + max_for_provider, |
| 197 result_refs.end(), &CompareMatchRelevance); | 206 result_refs.end(), &CompareMatchRelevance); |
| 198 matches_.clear(); | 207 matches_.clear(); |
| 199 for (size_t i = 0; i < max_for_provider; i++) { | 208 for (size_t i = 0; i < max_for_provider; i++) { |
| 200 matches_.push_back(ResultToMatch(*result_refs[i].result, | 209 AutocompleteMatch match = ResultToMatch(result_refs[i]); |
|
Peter Kasting
2011/08/09 20:53:00
Nit: I prefer constructor form to assignment form
dominich
2011/08/09 21:43:43
Done.
| |
| 201 result_refs[i].relevance)); | 210 UMA_HISTOGRAM_COUNTS_100("Autocomplete.Confidence_HistoryContents", |
| 211 match.confidence * 100); | |
| 212 matches_.push_back(match); | |
| 202 } | 213 } |
| 203 } | 214 } |
| 204 | 215 |
| 205 // TODO(mrossetti): Remove MatchInTitle once body_only_ becomes permanent. | 216 // TODO(mrossetti): Remove MatchInTitle once body_only_ becomes permanent. |
| 206 bool HistoryContentsProvider::MatchInTitle(const history::URLResult& result) { | 217 bool HistoryContentsProvider::MatchInTitle(const history::URLResult& result) { |
| 207 return !body_only_ && !result.title_match_positions().empty(); | 218 return !body_only_ && !result.title_match_positions().empty(); |
| 208 } | 219 } |
| 209 | 220 |
| 210 AutocompleteMatch HistoryContentsProvider::ResultToMatch( | 221 AutocompleteMatch HistoryContentsProvider::ResultToMatch( |
| 211 const history::URLResult& result, | 222 const MatchReference& match_reference) { |
| 212 int score) { | 223 const history::URLResult& result = *match_reference.result; |
| 213 AutocompleteMatch match(this, score, true, MatchInTitle(result) ? | 224 AutocompleteMatch match(this, match_reference.relevance, |
|
Peter Kasting
2011/08/09 20:53:00
Nit: This wrapping would be OK:
AutocompleteMat
dominich
2011/08/09 21:43:43
Done.
| |
| 214 AutocompleteMatch::HISTORY_TITLE : AutocompleteMatch::HISTORY_BODY); | 225 match_reference.confidence, true, |
| 226 MatchInTitle(result) ? | |
| 227 AutocompleteMatch::HISTORY_TITLE : | |
| 228 AutocompleteMatch::HISTORY_BODY); | |
| 215 match.contents = StringForURLDisplay(result.url(), true, trim_http_); | 229 match.contents = StringForURLDisplay(result.url(), true, trim_http_); |
| 216 match.fill_into_edit = | 230 match.fill_into_edit = |
| 217 AutocompleteInput::FormattedStringWithEquivalentMeaning(result.url(), | 231 AutocompleteInput::FormattedStringWithEquivalentMeaning(result.url(), |
| 218 match.contents); | 232 match.contents); |
| 219 match.destination_url = result.url(); | 233 match.destination_url = result.url(); |
| 220 match.contents_class.push_back( | 234 match.contents_class.push_back( |
| 221 ACMatchClassification(0, ACMatchClassification::URL)); | 235 ACMatchClassification(0, ACMatchClassification::URL)); |
| 222 match.description = result.title(); | 236 match.description = result.title(); |
| 223 match.starred = | 237 match.starred = |
| 224 (profile_->GetBookmarkModel() && | 238 (profile_->GetBookmarkModel() && |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 256 int HistoryContentsProvider::CalculateRelevance( | 270 int HistoryContentsProvider::CalculateRelevance( |
| 257 const history::URLResult& result) { | 271 const history::URLResult& result) { |
| 258 const bool in_title = MatchInTitle(result); | 272 const bool in_title = MatchInTitle(result); |
| 259 if (!profile_->GetBookmarkModel() || | 273 if (!profile_->GetBookmarkModel() || |
| 260 !profile_->GetBookmarkModel()->IsBookmarked(result.url())) | 274 !profile_->GetBookmarkModel()->IsBookmarked(result.url())) |
| 261 return in_title ? (700 + title_count_++) : (500 + contents_count_++); | 275 return in_title ? (700 + title_count_++) : (500 + contents_count_++); |
| 262 return in_title ? | 276 return in_title ? |
| 263 (1000 + star_title_count_++) : (550 + star_contents_count_++); | 277 (1000 + star_title_count_++) : (550 + star_contents_count_++); |
| 264 } | 278 } |
| 265 | 279 |
| 280 float HistoryContentsProvider::CalculateConfidence( | |
| 281 const history::URLResult& result, | |
| 282 const history::QueryResults& results) const { | |
| 283 // Calculate a score of [0, 0.5] based on visit count. | |
| 284 // TODO(dominic): Include typed count? | |
|
Peter Kasting
2011/08/09 20:53:00
If you're only going to use one, prefer typed_coun
dominich
2011/08/09 21:43:43
Done.
| |
| 285 float numerator = result.visit_count(); | |
| 286 float denominator = 0.0f; | |
| 287 for (std::vector<history::URLResult*>::const_iterator it = results.begin(); | |
| 288 it != results.end(); ++it) { | |
| 289 denominator += (*it)->visit_count(); | |
| 290 } | |
| 291 // It should only be equal to 0 if the result is not in the results vector. | |
| 292 DCHECK(denominator > 0); | |
| 293 float score = 0.5f * (numerator / denominator); | |
| 294 | |
| 295 // Add 0.5 if the URL is bookmarked to get a final range of [0, 1]. | |
|
Peter Kasting
2011/08/09 20:53:00
I think this gives far too much weight to bookmark
dominich
2011/08/09 21:43:43
Done.
| |
| 296 if (profile_->GetBookmarkModel() && | |
| 297 profile_->GetBookmarkModel()->IsBookmarked(result.url())) { | |
| 298 score += 0.5f; | |
| 299 } | |
| 300 | |
| 301 return score; | |
| 302 } | |
| 303 | |
| 266 void HistoryContentsProvider::QueryBookmarks(const AutocompleteInput& input) { | 304 void HistoryContentsProvider::QueryBookmarks(const AutocompleteInput& input) { |
| 267 BookmarkModel* bookmark_model = profile_->GetBookmarkModel(); | 305 BookmarkModel* bookmark_model = profile_->GetBookmarkModel(); |
| 268 if (!bookmark_model) | 306 if (!bookmark_model) |
| 269 return; | 307 return; |
| 270 | 308 |
| 271 DCHECK(results_.empty()); | 309 DCHECK(results_.empty()); |
| 272 | 310 |
| 273 TimeTicks start_time = TimeTicks::Now(); | 311 TimeTicks start_time = TimeTicks::Now(); |
| 274 std::vector<bookmark_utils::TitleMatch> matches; | 312 std::vector<bookmark_utils::TitleMatch> matches; |
| 275 bookmark_model->GetBookmarksWithTitlesMatching(input.text(), | 313 bookmark_model->GetBookmarksWithTitlesMatching(input.text(), |
| 276 kMaxMatches, &matches); | 314 kMaxMatches, &matches); |
| 277 for (size_t i = 0; i < matches.size(); ++i) | 315 for (size_t i = 0; i < matches.size(); ++i) |
| 278 AddBookmarkTitleMatchToResults(matches[i]); | 316 AddBookmarkTitleMatchToResults(matches[i]); |
| 279 UMA_HISTOGRAM_TIMES("Omnibox.QueryBookmarksTime", | 317 UMA_HISTOGRAM_TIMES("Omnibox.QueryBookmarksTime", |
| 280 TimeTicks::Now() - start_time); | 318 TimeTicks::Now() - start_time); |
| 281 } | 319 } |
| 282 | 320 |
| 283 void HistoryContentsProvider::AddBookmarkTitleMatchToResults( | 321 void HistoryContentsProvider::AddBookmarkTitleMatchToResults( |
| 284 const bookmark_utils::TitleMatch& match) { | 322 const bookmark_utils::TitleMatch& match) { |
| 285 history::URLResult url_result(match.node->url(), match.match_positions); | 323 history::URLResult url_result(match.node->url(), match.match_positions); |
| 286 url_result.set_title(match.node->GetTitle()); | 324 url_result.set_title(match.node->GetTitle()); |
| 287 results_.AppendURLBySwapping(&url_result); | 325 results_.AppendURLBySwapping(&url_result); |
| 288 } | 326 } |
| OLD | NEW |