Chromium Code Reviews| Index: chrome/browser/autocomplete/search_provider.cc |
| =================================================================== |
| --- chrome/browser/autocomplete/search_provider.cc (revision 91576) |
| +++ chrome/browser/autocomplete/search_provider.cc (working copy) |
| @@ -8,6 +8,7 @@ |
| #include <cmath> |
| #include "base/callback.h" |
| +#include "base/i18n/break_iterator.h" |
| #include "base/i18n/case_conversion.h" |
| #include "base/i18n/icu_string_conversions.h" |
| #include "base/message_loop.h" |
| @@ -37,6 +38,25 @@ |
| using base::Time; |
| using base::TimeDelta; |
| +namespace { |
| + |
| +bool HasMultipleWords(const string16& text) { |
| + base::i18n::BreakIterator i(text, base::i18n::BreakIterator::BREAK_WORD); |
| + bool found_word = false; |
|
sky
2011/07/07 02:49:15
nit: move this inside the if.
|
| + if (i.Init()) { |
| + while (i.Advance()) { |
| + if (i.IsWord()) { |
| + if (found_word) |
| + return true; |
| + found_word = true; |
| + } |
| + } |
| + } |
| + return false; |
| +} |
| + |
| +}; |
| + |
| // static |
| const int SearchProvider::kDefaultProviderURLFetcherID = 1; |
| // static |
| @@ -603,49 +623,59 @@ |
| bool is_keyword, |
| int did_not_accept_suggestion, |
| MatchMap* map) { |
| + bool base_prevent_inline_autocomplete = |
| + (input_.type() == AutocompleteInput::URL) || |
| + input_.prevent_inline_autocomplete(); |
| + const string16& input_text( |
| + is_keyword ? keyword_input_text_ : input_.text()); |
| + bool input_not_multiple_words = !HasMultipleWords(input_text); |
| + bool is_primary_provider = providers_.is_primary_provider(is_keyword); |
| + AutocompleteClassifier* classifier = profile_->GetAutocompleteClassifier(); |
| int last_relevance = 0; |
| - AutocompleteClassifier* classifier = profile_->GetAutocompleteClassifier(); |
| for (HistoryResults::const_iterator i(results.begin()); i != results.end(); |
| ++i) { |
| - // History returns results sorted for us. We force the relevance to decrease |
| - // so that the sort from history is honored. We should never end up with a |
| - // match having a relevance greater than the previous, but they might be |
| - // equal. If we didn't force the relevance to decrease and we ended up in a |
| - // situation where the relevance was equal, then which was shown first would |
| - // be random. |
| - // This uses >= to handle the case where 3 or more results have the same |
| - // relevance. |
| - bool term_looks_like_url = false; |
| + // Don't autocomplete multi-word queries that have only been seen once |
| + // unless the user has typed more than one word. |
| + bool prevent_inline_autocomplete = base_prevent_inline_autocomplete || |
| + (input_not_multiple_words && (i->visits < 2) && |
| + HasMultipleWords(i->term)); |
| + |
| // Don't autocomplete search terms that would normally be treated as URLs |
| - // when typed. For example, if the user searched for google.com and types |
| - // goog, don't autocomplete to the search term google.com. Otherwise, the |
| - // input will look like a URL but act like a search, which is confusing. |
| + // when typed. For example, if the user searched for "google.com" and types |
| + // "goog", don't autocomplete to the search term "google.com". Otherwise, |
| + // the input will look like a URL but act like a search, which is confusing. |
| // NOTE: We don't check this in the following cases: |
| // * When inline autocomplete is disabled, we won't be inline |
| // autocompleting this term, so we don't need to worry about confusion as |
| // much. This also prevents calling Classify() again from inside the |
| // classifier (which will corrupt state and likely crash), since the |
| - // classifier always disabled inline autocomplete. |
| + // classifier always disables inline autocomplete. |
| // * When the user has typed the whole term, the "what you typed" history |
| // match will outrank us for URL-like inputs anyway, so we need not do |
| // anything special. |
| - if (!input_.prevent_inline_autocomplete() && classifier && |
| - i->term != input_.text()) { |
| + if (!prevent_inline_autocomplete && classifier && (i->term != input_text)) { |
| AutocompleteMatch match; |
| classifier->Classify(i->term, string16(), false, false, &match, NULL); |
| - term_looks_like_url = match.transition == PageTransition::TYPED; |
| + prevent_inline_autocomplete = match.transition == PageTransition::TYPED; |
| } |
| - int relevance = CalculateRelevanceForHistory(i->time, term_looks_like_url, |
| - is_keyword); |
| + |
| + int relevance = CalculateRelevanceForHistory(i->time, is_primary_provider, |
| + prevent_inline_autocomplete); |
| + // History returns results sorted for us. We force the relevance to decrease |
| + // so that the sort from history is honored. We should never end up with a |
| + // match having a relevance greater than the previous, but they might be |
| + // equal. If we didn't force the relevance to decrease and we ended up in a |
| + // situation where the relevance was equal, then which was shown first would |
| + // be random. |
| + // This uses >= to handle the case where 3 or more results have the same |
| + // relevance. |
| if (i != results.begin() && relevance >= last_relevance) |
| relevance = last_relevance - 1; |
| last_relevance = relevance; |
| - AddMatchToMap(i->term, |
| - is_keyword ? keyword_input_text_ : input_.text(), |
| - relevance, |
| + |
| + AddMatchToMap(i->term, input_text, relevance, |
| AutocompleteMatch::SEARCH_HISTORY, did_not_accept_suggestion, |
| - is_keyword, input_.prevent_inline_autocomplete(), |
| - map); |
| + is_keyword, input_.prevent_inline_autocomplete(), map); |
| } |
| } |
| @@ -687,22 +717,20 @@ |
| } |
| } |
| -int SearchProvider::CalculateRelevanceForHistory(const Time& time, |
| - bool looks_like_url, |
| - bool is_keyword) const { |
| +int SearchProvider::CalculateRelevanceForHistory( |
| + const Time& time, |
| + bool is_primary_provider, |
| + bool prevent_inline_autocomplete) const { |
| // The relevance of past searches falls off over time. There are two distinct |
| // equations used. If the first equation is used (searches to the primary |
| - // provider with a type other than URL that don't autocomplete to a url) the |
| - // score starts at 1399 and falls to 1300. If the second equation is used the |
| - // relevance of a search 15 minutes ago is discounted about 50 points, while |
| - // the relevance of a search two weeks ago is discounted about 450 points. |
| + // provider that we want to inline autocomplete), the score starts at 1399 and |
| + // falls to 1300. If the second equation is used the relevance of a search 15 |
| + // minutes ago is discounted 50 points, while the relevance of a search two |
| + // weeks ago is discounted 450 points. |
| double elapsed_time = std::max((Time::Now() - time).InSecondsF(), 0.); |
| - |
| - if (providers_.is_primary_provider(is_keyword) && |
| - input_.type() != AutocompleteInput::URL && |
| - !input_.prevent_inline_autocomplete() && !looks_like_url) { |
| + if (is_primary_provider && !prevent_inline_autocomplete) { |
| // Searches with the past two days get a different curve. |
| - const double autocomplete_time= 2 * 24 * 60 * 60; |
| + const double autocomplete_time = 2 * 24 * 60 * 60; |
| if (elapsed_time < autocomplete_time) { |
| return 1399 - static_cast<int>(99 * |
| std::pow(elapsed_time / autocomplete_time, 2.5)); |
| @@ -716,10 +744,10 @@ |
| // Don't let scores go below 0. Negative relevance scores are meaningful in |
| // a different way. |
| int base_score; |
| - if (!providers_.is_primary_provider(is_keyword)) |
| + if (is_primary_provider) |
| + base_score = (input_.type() == AutocompleteInput::URL) ? 750 : 1050; |
| + else |
| base_score = 200; |
| - else |
| - base_score = (input_.type() == AutocompleteInput::URL) ? 750 : 1050; |
| return std::max(0, base_score - score_discount); |
| } |