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_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 |