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 |