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 AutocompleteMatch ac_match = |
272 history_matches.size() - 1 - i)); | 273 HistoryMatchToACMatch(params, match, history_matches, NORMAL, |
274 history_matches.size() - 1 - i); | |
275 UMA_HISTOGRAM_COUNTS_100("Autocomplete.Confidence_HistoryUrl", | |
276 ac_match.confidence * 100); | |
277 params->matches.push_back(ac_match); | |
273 } | 278 } |
274 } | 279 } |
275 | 280 |
276 // Called on the main thread when the query is complete. | 281 // Called on the main thread when the query is complete. |
277 void HistoryURLProvider::QueryComplete( | 282 void HistoryURLProvider::QueryComplete( |
278 HistoryURLProviderParams* params_gets_deleted) { | 283 HistoryURLProviderParams* params_gets_deleted) { |
279 // Ensure |params_gets_deleted| gets deleted on exit. | 284 // Ensure |params_gets_deleted| gets deleted on exit. |
280 scoped_ptr<HistoryURLProviderParams> params(params_gets_deleted); | 285 scoped_ptr<HistoryURLProviderParams> params(params_gets_deleted); |
281 | 286 |
282 // If the user hasn't already started another query, clear our member pointer | 287 // If the user hasn't already started another query, clear our member pointer |
(...skipping 12 matching lines...) Expand all Loading... | |
295 UpdateStarredStateOfMatches(); | 300 UpdateStarredStateOfMatches(); |
296 } | 301 } |
297 | 302 |
298 done_ = true; | 303 done_ = true; |
299 listener_->OnProviderUpdate(true); | 304 listener_->OnProviderUpdate(true); |
300 } | 305 } |
301 | 306 |
302 AutocompleteMatch HistoryURLProvider::SuggestExactInput( | 307 AutocompleteMatch HistoryURLProvider::SuggestExactInput( |
303 const AutocompleteInput& input, | 308 const AutocompleteInput& input, |
304 bool trim_http) { | 309 bool trim_http) { |
310 // TODO(dominich): Find a confidence measure for this. | |
305 AutocompleteMatch match(this, | 311 AutocompleteMatch match(this, |
306 CalculateRelevance(input.type(), WHAT_YOU_TYPED, 0), false, | 312 CalculateRelevance(input.type(), WHAT_YOU_TYPED, 0), 0.0f, false, |
307 AutocompleteMatch::URL_WHAT_YOU_TYPED); | 313 AutocompleteMatch::URL_WHAT_YOU_TYPED); |
314 UMA_HISTOGRAM_COUNTS_100("Autocomplete.Confidence_HistoryUrl", | |
315 match.confidence * 100); | |
308 | 316 |
309 const GURL& url = input.canonicalized_url(); | 317 const GURL& url = input.canonicalized_url(); |
310 if (url.is_valid()) { | 318 if (url.is_valid()) { |
311 match.destination_url = url; | 319 match.destination_url = url; |
312 | 320 |
313 // Trim off "http://" if the user didn't type it. | 321 // Trim off "http://" if the user didn't type it. |
314 // NOTE: We use TrimHttpPrefix() here rather than StringForURLDisplay() to | 322 // 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 | 323 // strip the scheme as we need to know the offset so we can adjust the |
316 // |match_location| below. StringForURLDisplay() and TrimHttpPrefix() have | 324 // |match_location| below. StringForURLDisplay() and TrimHttpPrefix() have |
317 // slightly different behavior as well (the latter will strip even without | 325 // 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. | 412 // Promote as an exact match. |
405 match->relevance = CalculateRelevance(input.type(), type, 0); | 413 match->relevance = CalculateRelevance(input.type(), type, 0); |
406 | 414 |
407 // Put it on the front of the HistoryMatches for redirect culling. | 415 // Put it on the front of the HistoryMatches for redirect culling. |
408 EnsureMatchPresent(info, string16::npos, false, matches, true); | 416 EnsureMatchPresent(info, string16::npos, false, matches, true); |
409 return true; | 417 return true; |
410 } | 418 } |
411 | 419 |
412 bool HistoryURLProvider::PromoteMatchForInlineAutocomplete( | 420 bool HistoryURLProvider::PromoteMatchForInlineAutocomplete( |
413 HistoryURLProviderParams* params, | 421 HistoryURLProviderParams* params, |
414 const HistoryMatch& match) { | 422 const HistoryMatch& match, |
423 const HistoryMatches& matches) { | |
415 // Promote the first match if it's been typed at least n times, where n == 1 | 424 // 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 | 425 // 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 | 426 // 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 | 427 // 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 | 428 // 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. | 429 // hand, we wouldn't want to immediately start autocompleting it. |
421 if (!match.url_info.typed_count() || | 430 if (!match.url_info.typed_count() || |
422 ((match.url_info.typed_count() == 1) && | 431 ((match.url_info.typed_count() == 1) && |
423 !history::IsHostOnly(match.url_info.url()))) | 432 !history::IsHostOnly(match.url_info.url()))) |
424 return false; | 433 return false; |
425 | 434 |
426 // In the case where the user has typed "foo.com" and visited (but not typed) | 435 // 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 | 436 // "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 | 437 // 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 | 438 // 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 | 439 // 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. | 440 // future pass from suggesting the exact input as a better match. |
432 params->dont_suggest_exact_input = true; | 441 params->dont_suggest_exact_input = true; |
433 params->matches.push_back(HistoryMatchToACMatch(params, match, | 442 params->matches.push_back(HistoryMatchToACMatch(params, match, matches, |
434 INLINE_AUTOCOMPLETE, 0)); | 443 INLINE_AUTOCOMPLETE, 0)); |
435 return true; | 444 return true; |
436 } | 445 } |
437 | 446 |
438 HistoryURLProvider::~HistoryURLProvider() {} | 447 HistoryURLProvider::~HistoryURLProvider() {} |
439 | 448 |
440 // static | 449 // static |
441 history::Prefixes HistoryURLProvider::GetPrefixes() { | 450 history::Prefixes HistoryURLProvider::GetPrefixes() { |
442 // We'll complete text following these prefixes. | 451 // We'll complete text following these prefixes. |
443 // NOTE: There's no requirement that these be in any particular order. | 452 // NOTE: There's no requirement that these be in any particular order. |
(...skipping 20 matching lines...) Expand all Loading... | |
464 | 473 |
465 case WHAT_YOU_TYPED: | 474 case WHAT_YOU_TYPED: |
466 return 1200; | 475 return 1200; |
467 | 476 |
468 default: | 477 default: |
469 return 900 + static_cast<int>(match_number); | 478 return 900 + static_cast<int>(match_number); |
470 } | 479 } |
471 } | 480 } |
472 | 481 |
473 // static | 482 // static |
483 float HistoryURLProvider::CalculateConfidence( | |
484 const history::HistoryMatch& match, | |
485 const history::HistoryMatches& matches) { | |
mrossetti
2011/08/09 23:40:43
I think this should just be the precalculated sum
| |
486 // TODO(dominich): Take into account bookmarked page? | |
487 // TODO(dominich): See CompareHistoryMatch for more measures to include. | |
488 // Using typed count in place of visit count as: | |
489 // - It's a better indicator of what the user wants to open given that they | |
490 // are typing in the address bar (users tend to open certain URLs by typing | |
491 // and others by e.g. bookmarks, so visit_count is a good indicator of | |
492 // overall interest but a bad one for specifically omnibox interest). | |
493 // - Since the DB query is sorted by typed_count, the results may be | |
494 // effectively a random selection as far as visit_counts are concerned | |
495 // (meaning many high-visit_count-URLs may be present in one query and | |
496 // absent in a similar one), leading to wild swings in confidence for the | |
497 // same result across distinct queries. | |
498 float numerator = match.url_info.typed_count(); | |
499 float denominator = 0.0f; | |
500 for (history::HistoryMatches::const_iterator it = matches.begin(); | |
mrossetti
2011/08/09 23:40:43
Same thought as with the HistoryQuickProvider: why
dominich
2011/08/10 16:10:13
Once the algorithm for the calculation settles to
| |
501 it != matches.end(); ++it) { | |
502 denominator += it->url_info.typed_count(); | |
503 } | |
504 DCHECK(denominator > 0); | |
505 return numerator / denominator; | |
506 } | |
507 | |
508 // static | |
474 void HistoryURLProvider::PromoteOrCreateShorterSuggestion( | 509 void HistoryURLProvider::PromoteOrCreateShorterSuggestion( |
475 history::URLDatabase* db, | 510 history::URLDatabase* db, |
476 const HistoryURLProviderParams& params, | 511 const HistoryURLProviderParams& params, |
477 bool have_what_you_typed_match, | 512 bool have_what_you_typed_match, |
478 const AutocompleteMatch& what_you_typed_match, | 513 const AutocompleteMatch& what_you_typed_match, |
479 HistoryMatches* matches) { | 514 HistoryMatches* matches) { |
480 if (matches->empty()) | 515 if (matches->empty()) |
481 return; // No matches, nothing to do. | 516 return; // No matches, nothing to do. |
482 | 517 |
483 // Determine the base URL from which to search, and whether that URL could | 518 // 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); | 802 next = matches->erase(next); |
768 if (static_cast<size_t>(next - matches->begin()) < next_index) | 803 if (static_cast<size_t>(next - matches->begin()) < next_index) |
769 next_index--; | 804 next_index--; |
770 } | 805 } |
771 return next_index; | 806 return next_index; |
772 } | 807 } |
773 | 808 |
774 AutocompleteMatch HistoryURLProvider::HistoryMatchToACMatch( | 809 AutocompleteMatch HistoryURLProvider::HistoryMatchToACMatch( |
775 HistoryURLProviderParams* params, | 810 HistoryURLProviderParams* params, |
776 const HistoryMatch& history_match, | 811 const HistoryMatch& history_match, |
812 const HistoryMatches& history_matches, | |
777 MatchType match_type, | 813 MatchType match_type, |
778 size_t match_number) { | 814 size_t match_number) { |
779 const history::URLRow& info = history_match.url_info; | 815 const history::URLRow& info = history_match.url_info; |
780 AutocompleteMatch match(this, | 816 AutocompleteMatch match(this, |
781 CalculateRelevance(params->input.type(), match_type, match_number), | 817 CalculateRelevance(params->input.type(), match_type, match_number), |
818 CalculateConfidence(history_match, history_matches), | |
782 !!info.visit_count(), AutocompleteMatch::HISTORY_URL); | 819 !!info.visit_count(), AutocompleteMatch::HISTORY_URL); |
783 match.destination_url = info.url(); | 820 match.destination_url = info.url(); |
784 DCHECK(match.destination_url.is_valid()); | 821 DCHECK(match.destination_url.is_valid()); |
785 size_t inline_autocomplete_offset = | 822 size_t inline_autocomplete_offset = |
786 history_match.input_location + params->input.text().length(); | 823 history_match.input_location + params->input.text().length(); |
787 std::string languages = (match_type == WHAT_YOU_TYPED) ? | 824 std::string languages = (match_type == WHAT_YOU_TYPED) ? |
788 std::string() : params->languages; | 825 std::string() : params->languages; |
789 const net::FormatUrlTypes format_types = net::kFormatUrlOmitAll & | 826 const net::FormatUrlTypes format_types = net::kFormatUrlOmitAll & |
790 ~((params->trim_http && !history_match.match_in_scheme) ? | 827 ~((params->trim_http && !history_match.match_in_scheme) ? |
791 0 : net::kFormatUrlOmitHTTP); | 828 0 : net::kFormatUrlOmitHTTP); |
(...skipping 23 matching lines...) Expand all Loading... | |
815 &match.contents_class); | 852 &match.contents_class); |
816 } | 853 } |
817 match.description = info.title(); | 854 match.description = info.title(); |
818 AutocompleteMatch::ClassifyMatchInString(params->input.text(), | 855 AutocompleteMatch::ClassifyMatchInString(params->input.text(), |
819 info.title(), | 856 info.title(), |
820 ACMatchClassification::NONE, | 857 ACMatchClassification::NONE, |
821 &match.description_class); | 858 &match.description_class); |
822 | 859 |
823 return match; | 860 return match; |
824 } | 861 } |
OLD | NEW |