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); |
} |