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_url_provider.h" | 5 #include "chrome/browser/autocomplete/history_url_provider.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/basictypes.h" | 9 #include "base/basictypes.h" |
10 #include "base/message_loop.h" | 10 #include "base/message_loop.h" |
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
238 if (what_you_typed_match.is_history_what_you_typed_match && | 238 if (what_you_typed_match.is_history_what_you_typed_match && |
239 (!backend || !params->dont_suggest_exact_input) && | 239 (!backend || !params->dont_suggest_exact_input) && |
240 FixupExactSuggestion(db, params->input, &what_you_typed_match, | 240 FixupExactSuggestion(db, params->input, &what_you_typed_match, |
241 &history_matches)) { | 241 &history_matches)) { |
242 // Got an exact match for the user's input. Treat it as the best match | 242 // Got an exact match for the user's input. Treat it as the best match |
243 // regardless of the input type. | 243 // regardless of the input type. |
244 exact_suggestion = 1; | 244 exact_suggestion = 1; |
245 params->matches.push_back(what_you_typed_match); | 245 params->matches.push_back(what_you_typed_match); |
246 } else if (params->prevent_inline_autocomplete || | 246 } else if (params->prevent_inline_autocomplete || |
247 history_matches.empty() || | 247 history_matches.empty() || |
248 !PromoteMatchForInlineAutocomplete(params, history_matches.front())) { | 248 !PromoteMatchForInlineAutocomplete(params, history_matches.front(), |
249 history_matches)) { | |
249 // Failed to promote any URLs for inline autocompletion. Use the What You | 250 // Failed to promote any URLs for inline autocompletion. Use the What You |
250 // Typed match, if we have it. | 251 // Typed match, if we have it. |
251 first_match = 0; | 252 first_match = 0; |
252 if (have_what_you_typed_match) | 253 if (have_what_you_typed_match) |
253 params->matches.push_back(what_you_typed_match); | 254 params->matches.push_back(what_you_typed_match); |
254 } | 255 } |
255 | 256 |
256 // This is the end of the synchronous pass. | 257 // This is the end of the synchronous pass. |
257 if (!backend) | 258 if (!backend) |
258 return; | 259 return; |
259 | 260 |
260 // Remove redirects and trim list to size. We want to provide up to | 261 // Remove redirects and trim list to size. We want to provide up to |
261 // kMaxMatches results plus the What You Typed result, if it was added to | 262 // kMaxMatches results plus the What You Typed result, if it was added to |
262 // |history_matches| above. | 263 // |history_matches| above. |
263 CullRedirects(backend, &history_matches, kMaxMatches + exact_suggestion); | 264 CullRedirects(backend, &history_matches, kMaxMatches + exact_suggestion); |
264 | 265 |
265 // Convert the history matches to autocomplete matches. | 266 // Convert the history matches to autocomplete matches. |
266 for (size_t i = first_match; i < history_matches.size(); ++i) { | 267 for (size_t i = first_match; i < history_matches.size(); ++i) { |
267 const HistoryMatch& match = history_matches[i]; | 268 const HistoryMatch& match = history_matches[i]; |
268 DCHECK(!have_what_you_typed_match || | 269 DCHECK(!have_what_you_typed_match || |
269 (match.url_info.url() != | 270 (match.url_info.url() != |
270 GURL(params->matches.front().destination_url))); | 271 GURL(params->matches.front().destination_url))); |
271 params->matches.push_back(HistoryMatchToACMatch(params, match, NORMAL, | 272 // TODO(dominich): Should this be history_matches.size() - first_match - i? |
Peter Kasting
2011/08/09 20:53:00
No, it should not.
dominich
2011/08/09 21:43:43
Done.
| |
272 history_matches.size() - 1 - i)); | 273 AutocompleteMatch ac_match = |
274 HistoryMatchToACMatch(params, match, history_matches, NORMAL, | |
275 history_matches.size() - 1 - i); | |
276 UMA_HISTOGRAM_COUNTS_100("Autocomplete.Confidence_HistoryUrl", | |
277 ac_match.confidence * 100); | |
278 params->matches.push_back(ac_match); | |
273 } | 279 } |
274 } | 280 } |
275 | 281 |
276 // Called on the main thread when the query is complete. | 282 // Called on the main thread when the query is complete. |
277 void HistoryURLProvider::QueryComplete( | 283 void HistoryURLProvider::QueryComplete( |
278 HistoryURLProviderParams* params_gets_deleted) { | 284 HistoryURLProviderParams* params_gets_deleted) { |
279 // Ensure |params_gets_deleted| gets deleted on exit. | 285 // Ensure |params_gets_deleted| gets deleted on exit. |
280 scoped_ptr<HistoryURLProviderParams> params(params_gets_deleted); | 286 scoped_ptr<HistoryURLProviderParams> params(params_gets_deleted); |
281 | 287 |
282 // If the user hasn't already started another query, clear our member pointer | 288 // If the user hasn't already started another query, clear our member pointer |
(...skipping 12 matching lines...) Expand all Loading... | |
295 UpdateStarredStateOfMatches(); | 301 UpdateStarredStateOfMatches(); |
296 } | 302 } |
297 | 303 |
298 done_ = true; | 304 done_ = true; |
299 listener_->OnProviderUpdate(true); | 305 listener_->OnProviderUpdate(true); |
300 } | 306 } |
301 | 307 |
302 AutocompleteMatch HistoryURLProvider::SuggestExactInput( | 308 AutocompleteMatch HistoryURLProvider::SuggestExactInput( |
303 const AutocompleteInput& input, | 309 const AutocompleteInput& input, |
304 bool trim_http) { | 310 bool trim_http) { |
311 // TODO(dominich): Check that 100% confidence makes sense for exact input. | |
Peter Kasting
2011/08/09 20:53:00
It doesn't. This will mean the what-you-typed mat
dominich
2011/08/09 21:43:43
You're mixing up the notion of rank and confidence
| |
305 AutocompleteMatch match(this, | 312 AutocompleteMatch match(this, |
306 CalculateRelevance(input.type(), WHAT_YOU_TYPED, 0), false, | 313 CalculateRelevance(input.type(), WHAT_YOU_TYPED, 0), 1.0f, false, |
307 AutocompleteMatch::URL_WHAT_YOU_TYPED); | 314 AutocompleteMatch::URL_WHAT_YOU_TYPED); |
315 UMA_HISTOGRAM_COUNTS_100("Autocomplete.Confidence_HistoryUrl", | |
316 match.confidence * 100); | |
308 | 317 |
309 const GURL& url = input.canonicalized_url(); | 318 const GURL& url = input.canonicalized_url(); |
310 if (url.is_valid()) { | 319 if (url.is_valid()) { |
311 match.destination_url = url; | 320 match.destination_url = url; |
312 | 321 |
313 // Trim off "http://" if the user didn't type it. | 322 // Trim off "http://" if the user didn't type it. |
314 // NOTE: We use TrimHttpPrefix() here rather than StringForURLDisplay() to | 323 // NOTE: We use TrimHttpPrefix() here rather than StringForURLDisplay() to |
315 // strip the scheme as we need to know the offset so we can adjust the | 324 // strip the scheme as we need to know the offset so we can adjust the |
316 // |match_location| below. StringForURLDisplay() and TrimHttpPrefix() have | 325 // |match_location| below. StringForURLDisplay() and TrimHttpPrefix() have |
317 // slightly different behavior as well (the latter will strip even without | 326 // slightly different behavior as well (the latter will strip even without |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
404 // Promote as an exact match. | 413 // Promote as an exact match. |
405 match->relevance = CalculateRelevance(input.type(), type, 0); | 414 match->relevance = CalculateRelevance(input.type(), type, 0); |
406 | 415 |
407 // Put it on the front of the HistoryMatches for redirect culling. | 416 // Put it on the front of the HistoryMatches for redirect culling. |
408 EnsureMatchPresent(info, string16::npos, false, matches, true); | 417 EnsureMatchPresent(info, string16::npos, false, matches, true); |
409 return true; | 418 return true; |
410 } | 419 } |
411 | 420 |
412 bool HistoryURLProvider::PromoteMatchForInlineAutocomplete( | 421 bool HistoryURLProvider::PromoteMatchForInlineAutocomplete( |
413 HistoryURLProviderParams* params, | 422 HistoryURLProviderParams* params, |
414 const HistoryMatch& match) { | 423 const HistoryMatch& match, |
424 const HistoryMatches& matches) { | |
415 // Promote the first match if it's been typed at least n times, where n == 1 | 425 // Promote the first match if it's been typed at least n times, where n == 1 |
416 // for "simple" (host-only) URLs and n == 2 for others. We set a higher bar | 426 // for "simple" (host-only) URLs and n == 2 for others. We set a higher bar |
417 // for these long URLs because it's less likely that users will want to visit | 427 // for these long URLs because it's less likely that users will want to visit |
418 // them again. Even though we don't increment the typed_count for pasted-in | 428 // them again. Even though we don't increment the typed_count for pasted-in |
419 // URLs, if the user manually edits the URL or types some long thing in by | 429 // URLs, if the user manually edits the URL or types some long thing in by |
420 // hand, we wouldn't want to immediately start autocompleting it. | 430 // hand, we wouldn't want to immediately start autocompleting it. |
421 if (!match.url_info.typed_count() || | 431 if (!match.url_info.typed_count() || |
422 ((match.url_info.typed_count() == 1) && | 432 ((match.url_info.typed_count() == 1) && |
423 !history::IsHostOnly(match.url_info.url()))) | 433 !history::IsHostOnly(match.url_info.url()))) |
424 return false; | 434 return false; |
425 | 435 |
426 // In the case where the user has typed "foo.com" and visited (but not typed) | 436 // In the case where the user has typed "foo.com" and visited (but not typed) |
427 // "foo/", and the input is "foo", we can reach here for "foo.com" during the | 437 // "foo/", and the input is "foo", we can reach here for "foo.com" during the |
428 // first pass but have the second pass suggest the exact input as a better | 438 // first pass but have the second pass suggest the exact input as a better |
429 // URL. Since we need both passes to agree, and since during the first pass | 439 // URL. Since we need both passes to agree, and since during the first pass |
430 // there's no way to know about "foo/", make reaching this point prevent any | 440 // there's no way to know about "foo/", make reaching this point prevent any |
431 // future pass from suggesting the exact input as a better match. | 441 // future pass from suggesting the exact input as a better match. |
432 params->dont_suggest_exact_input = true; | 442 params->dont_suggest_exact_input = true; |
433 params->matches.push_back(HistoryMatchToACMatch(params, match, | 443 params->matches.push_back(HistoryMatchToACMatch(params, match, matches, |
434 INLINE_AUTOCOMPLETE, 0)); | 444 INLINE_AUTOCOMPLETE, 0)); |
435 return true; | 445 return true; |
436 } | 446 } |
437 | 447 |
438 HistoryURLProvider::~HistoryURLProvider() {} | 448 HistoryURLProvider::~HistoryURLProvider() {} |
439 | 449 |
440 // static | 450 // static |
441 history::Prefixes HistoryURLProvider::GetPrefixes() { | 451 history::Prefixes HistoryURLProvider::GetPrefixes() { |
442 // We'll complete text following these prefixes. | 452 // We'll complete text following these prefixes. |
443 // NOTE: There's no requirement that these be in any particular order. | 453 // NOTE: There's no requirement that these be in any particular order. |
(...skipping 20 matching lines...) Expand all Loading... | |
464 | 474 |
465 case WHAT_YOU_TYPED: | 475 case WHAT_YOU_TYPED: |
466 return 1200; | 476 return 1200; |
467 | 477 |
468 default: | 478 default: |
469 return 900 + static_cast<int>(match_number); | 479 return 900 + static_cast<int>(match_number); |
470 } | 480 } |
471 } | 481 } |
472 | 482 |
473 // static | 483 // static |
484 float HistoryURLProvider::CalculateConfidence( | |
485 const history::HistoryMatch& match, | |
486 const history::HistoryMatches& matches) { | |
487 // TODO(dominich): Take into account typed count? | |
Peter Kasting
2011/08/09 20:53:00
See comments in HCP for why typed_count is better
dominich
2011/08/09 21:43:43
It looks like CompareHistoryMatch is a good starti
| |
488 // TODO(dominich): Take into account bookmarked page? | |
489 float numerator = match.url_info.visit_count(); | |
490 float denominator = 0.0f; | |
491 for (history::HistoryMatches::const_iterator it = matches.begin(); | |
492 it != matches.end(); ++it) { | |
Peter Kasting
2011/08/09 20:53:00
Nit: No need for {}
dominich
2011/08/09 21:43:43
See comment on HCP as to why I prefer to keep this
| |
493 denominator += it->url_info.visit_count(); | |
494 } | |
495 DCHECK(denominator > 0); | |
496 return numerator / denominator; | |
497 } | |
498 | |
499 // static | |
474 void HistoryURLProvider::PromoteOrCreateShorterSuggestion( | 500 void HistoryURLProvider::PromoteOrCreateShorterSuggestion( |
475 history::URLDatabase* db, | 501 history::URLDatabase* db, |
476 const HistoryURLProviderParams& params, | 502 const HistoryURLProviderParams& params, |
477 bool have_what_you_typed_match, | 503 bool have_what_you_typed_match, |
478 const AutocompleteMatch& what_you_typed_match, | 504 const AutocompleteMatch& what_you_typed_match, |
479 HistoryMatches* matches) { | 505 HistoryMatches* matches) { |
480 if (matches->empty()) | 506 if (matches->empty()) |
481 return; // No matches, nothing to do. | 507 return; // No matches, nothing to do. |
482 | 508 |
483 // Determine the base URL from which to search, and whether that URL could | 509 // Determine the base URL from which to search, and whether that URL could |
(...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
767 next = matches->erase(next); | 793 next = matches->erase(next); |
768 if (static_cast<size_t>(next - matches->begin()) < next_index) | 794 if (static_cast<size_t>(next - matches->begin()) < next_index) |
769 next_index--; | 795 next_index--; |
770 } | 796 } |
771 return next_index; | 797 return next_index; |
772 } | 798 } |
773 | 799 |
774 AutocompleteMatch HistoryURLProvider::HistoryMatchToACMatch( | 800 AutocompleteMatch HistoryURLProvider::HistoryMatchToACMatch( |
775 HistoryURLProviderParams* params, | 801 HistoryURLProviderParams* params, |
776 const HistoryMatch& history_match, | 802 const HistoryMatch& history_match, |
803 const HistoryMatches& history_matches, | |
777 MatchType match_type, | 804 MatchType match_type, |
778 size_t match_number) { | 805 size_t match_number) { |
779 const history::URLRow& info = history_match.url_info; | 806 const history::URLRow& info = history_match.url_info; |
780 AutocompleteMatch match(this, | 807 AutocompleteMatch match(this, |
781 CalculateRelevance(params->input.type(), match_type, match_number), | 808 CalculateRelevance(params->input.type(), match_type, match_number), |
809 CalculateConfidence(history_match, history_matches), | |
782 !!info.visit_count(), AutocompleteMatch::HISTORY_URL); | 810 !!info.visit_count(), AutocompleteMatch::HISTORY_URL); |
783 match.destination_url = info.url(); | 811 match.destination_url = info.url(); |
784 DCHECK(match.destination_url.is_valid()); | 812 DCHECK(match.destination_url.is_valid()); |
785 size_t inline_autocomplete_offset = | 813 size_t inline_autocomplete_offset = |
786 history_match.input_location + params->input.text().length(); | 814 history_match.input_location + params->input.text().length(); |
787 std::string languages = (match_type == WHAT_YOU_TYPED) ? | 815 std::string languages = (match_type == WHAT_YOU_TYPED) ? |
788 std::string() : params->languages; | 816 std::string() : params->languages; |
789 const net::FormatUrlTypes format_types = net::kFormatUrlOmitAll & | 817 const net::FormatUrlTypes format_types = net::kFormatUrlOmitAll & |
790 ~((params->trim_http && !history_match.match_in_scheme) ? | 818 ~((params->trim_http && !history_match.match_in_scheme) ? |
791 0 : net::kFormatUrlOmitHTTP); | 819 0 : net::kFormatUrlOmitHTTP); |
(...skipping 23 matching lines...) Expand all Loading... | |
815 &match.contents_class); | 843 &match.contents_class); |
816 } | 844 } |
817 match.description = info.title(); | 845 match.description = info.title(); |
818 AutocompleteMatch::ClassifyMatchInString(params->input.text(), | 846 AutocompleteMatch::ClassifyMatchInString(params->input.text(), |
819 info.title(), | 847 info.title(), |
820 ACMatchClassification::NONE, | 848 ACMatchClassification::NONE, |
821 &match.description_class); | 849 &match.description_class); |
822 | 850 |
823 return match; | 851 return match; |
824 } | 852 } |
OLD | NEW |