summaryrefslogtreecommitdiffstats
path: root/chrome/browser/autocomplete
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/autocomplete')
-rw-r--r--chrome/browser/autocomplete/autocomplete_match.cc7
-rw-r--r--chrome/browser/autocomplete/search_provider.cc558
-rw-r--r--chrome/browser/autocomplete/search_provider.h103
-rw-r--r--chrome/browser/autocomplete/search_provider_unittest.cc32
-rw-r--r--chrome/browser/autocomplete/zero_suggest_provider.cc16
5 files changed, 360 insertions, 356 deletions
diff --git a/chrome/browser/autocomplete/autocomplete_match.cc b/chrome/browser/autocomplete/autocomplete_match.cc
index 5eccdb7..22a049c 100644
--- a/chrome/browser/autocomplete/autocomplete_match.cc
+++ b/chrome/browser/autocomplete/autocomplete_match.cc
@@ -9,7 +9,6 @@
#include "base/strings/string16.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time.h"
#include "chrome/browser/autocomplete/autocomplete_provider.h"
@@ -421,14 +420,14 @@ TemplateURL* AutocompleteMatch::GetTemplateURL(
void AutocompleteMatch::RecordAdditionalInfo(const std::string& property,
const std::string& value) {
- DCHECK(property.size());
- DCHECK(value.size());
+ DCHECK(!property.empty());
+ DCHECK(!value.empty());
additional_info[property] = value;
}
void AutocompleteMatch::RecordAdditionalInfo(const std::string& property,
int value) {
- RecordAdditionalInfo(property, base::StringPrintf("%d", value));
+ RecordAdditionalInfo(property, base::IntToString(value));
}
void AutocompleteMatch::RecordAdditionalInfo(const std::string& property,
diff --git a/chrome/browser/autocomplete/search_provider.cc b/chrome/browser/autocomplete/search_provider.cc
index 93f68ff..45f7803 100644
--- a/chrome/browser/autocomplete/search_provider.cc
+++ b/chrome/browser/autocomplete/search_provider.cc
@@ -51,8 +51,8 @@
#include "net/url_request/url_request_status.h"
#include "ui/base/l10n/l10n_util.h"
-using base::Time;
-using base::TimeDelta;
+
+// Helpers --------------------------------------------------------------------
namespace {
@@ -115,15 +115,128 @@ const TemplateURL* SearchProvider::Providers::GetKeywordProviderURL() const {
}
+// SearchProvider::Result -----------------------------------------------------
+
+SearchProvider::Result::Result(bool from_keyword_provider,
+ int relevance)
+ : from_keyword_provider_(from_keyword_provider),
+ relevance_(relevance) {
+}
+
+SearchProvider::Result::~Result() {
+}
+
+
+// SearchProvider::SuggestResult ----------------------------------------------
+
+SearchProvider::SuggestResult::SuggestResult(const string16& suggestion,
+ bool from_keyword_provider,
+ int relevance)
+ : Result(from_keyword_provider, relevance),
+ suggestion_(suggestion) {
+}
+
+SearchProvider::SuggestResult::~SuggestResult() {
+}
+
+bool SearchProvider::SuggestResult::IsInlineable(const string16& input) const {
+ return StartsWith(suggestion_, input, false);
+}
+
+int SearchProvider::SuggestResult::CalculateRelevance(
+ const AutocompleteInput& input,
+ bool keyword_provider_requested) const {
+ if (!from_keyword_provider_ && keyword_provider_requested)
+ return 100;
+ return ((input.type() == AutocompleteInput::URL) ? 300 : 600);
+}
+
+
+// SearchProvider::NavigationResult -------------------------------------------
+
+SearchProvider::NavigationResult::NavigationResult(
+ const AutocompleteProvider& provider,
+ const GURL& url,
+ const string16& description,
+ bool from_keyword_provider,
+ int relevance)
+ : Result(from_keyword_provider, relevance),
+ url_(url),
+ formatted_url_(AutocompleteInput::FormattedStringWithEquivalentMeaning(
+ url, provider.StringForURLDisplay(url, true, false))),
+ description_(description) {
+ DCHECK(url_.is_valid());
+}
+
+SearchProvider::NavigationResult::~NavigationResult() {
+}
+
+bool SearchProvider::NavigationResult::IsInlineable(
+ const string16& input) const {
+ return URLPrefix::BestURLPrefix(formatted_url_, input) != NULL;
+}
+
+int SearchProvider::NavigationResult::CalculateRelevance(
+ const AutocompleteInput& input,
+ bool keyword_provider_requested) const {
+ return (from_keyword_provider_ || !keyword_provider_requested) ? 800 : 150;
+}
+
+
+// SearchProvider::CompareScoredResults ---------------------------------------
+
+class SearchProvider::CompareScoredResults {
+ public:
+ bool operator()(const Result& a, const Result& b) {
+ // Sort in descending relevance order.
+ return a.relevance() > b.relevance();
+ }
+};
+
+
+// SearchProvider::Results ----------------------------------------------------
+
+SearchProvider::Results::Results()
+ : has_suggested_relevance(false),
+ verbatim_relevance(-1) {
+}
+
+SearchProvider::Results::~Results() {
+}
+
+void SearchProvider::Results::Clear() {
+ suggest_results.clear();
+ navigation_results.clear();
+ has_suggested_relevance = false;
+ verbatim_relevance = -1;
+}
+
+bool SearchProvider::Results::HasServerProvidedScores() const {
+ if (verbatim_relevance >= 0)
+ return true;
+
+ return has_suggested_relevance;
+}
// SearchProvider -------------------------------------------------------------
// static
const int SearchProvider::kDefaultProviderURLFetcherID = 1;
-// static
const int SearchProvider::kKeywordProviderURLFetcherID = 2;
-// static
int SearchProvider::kMinimumTimeBetweenSuggestQueriesMs = 100;
+SearchProvider::SearchProvider(AutocompleteProviderListener* listener,
+ Profile* profile)
+ : AutocompleteProvider(listener, profile,
+ AutocompleteProvider::TYPE_SEARCH),
+ providers_(TemplateURLServiceFactory::GetForProfile(profile)),
+ suggest_results_pending_(0),
+ instant_finalized_(false),
+ field_trial_triggered_(false),
+ field_trial_triggered_in_session_(false),
+ suppress_search_suggestions_(false),
+ omnibox_start_margin_(-1) {
+}
+
// static
AutocompleteMatch SearchProvider::CreateSearchSuggestion(
Profile* profile,
@@ -219,17 +332,25 @@ AutocompleteMatch SearchProvider::CreateSearchSuggestion(
return match;
}
-SearchProvider::SearchProvider(AutocompleteProviderListener* listener,
- Profile* profile)
- : AutocompleteProvider(listener, profile,
- AutocompleteProvider::TYPE_SEARCH),
- providers_(TemplateURLServiceFactory::GetForProfile(profile)),
- suggest_results_pending_(0),
- instant_finalized_(false),
- field_trial_triggered_(false),
- field_trial_triggered_in_session_(false),
- suppress_search_suggestions_(false),
- omnibox_start_margin_(-1) {
+void SearchProvider::AddProviderInfo(ProvidersInfo* provider_info) const {
+ provider_info->push_back(metrics::OmniboxEventProto_ProviderInfo());
+ metrics::OmniboxEventProto_ProviderInfo& new_entry = provider_info->back();
+ new_entry.set_provider(AsOmniboxEventProviderType());
+ new_entry.set_provider_done(done_);
+ std::vector<uint32> field_trial_hashes;
+ OmniboxFieldTrial::GetActiveSuggestFieldTrialHashes(&field_trial_hashes);
+ for (size_t i = 0; i < field_trial_hashes.size(); ++i) {
+ if (field_trial_triggered_)
+ new_entry.mutable_field_trial_triggered()->Add(field_trial_hashes[i]);
+ if (field_trial_triggered_in_session_) {
+ new_entry.mutable_field_trial_triggered_in_session()->Add(
+ field_trial_hashes[i]);
+ }
+ }
+}
+
+void SearchProvider::ResetSession() {
+ field_trial_triggered_in_session_ = false;
}
void SearchProvider::FinalizeInstantQuery(const string16& input_text,
@@ -291,12 +412,9 @@ void SearchProvider::FinalizeInstantQuery(const string16& input_text,
// it gets autocompleted; use kNonURLVerbatimRelevance rather than
// verbatim_relevance so that the score does not change if the user keeps
// typing and the input changes from type UNKNOWN to URL.
- matches_.push_back(NavigationToMatch(
- NavigationResult(*this,
- GURL(UTF16ToUTF8(suggestion.text)),
- string16(),
- false,
- kNonURLVerbatimRelevance + 1)));
+ matches_.push_back(NavigationToMatch(NavigationResult(
+ *this, GURL(UTF16ToUTF8(suggestion.text)), string16(), false,
+ kNonURLVerbatimRelevance + 1)));
results_updated = true;
}
@@ -321,6 +439,85 @@ void SearchProvider::SetOmniboxStartMargin(int omnibox_start_margin) {
omnibox_start_margin_ = omnibox_start_margin;
}
+bool SearchProvider::IsNonInstantSearchDone() const {
+ return !timer_.IsRunning() && (suggest_results_pending_ == 0);
+}
+
+SearchProvider::~SearchProvider() {
+}
+
+// static
+void SearchProvider::RemoveStaleResults(const string16& input,
+ int verbatim_relevance,
+ SuggestResults* suggest_results,
+ NavigationResults* navigation_results) {
+ DCHECK_GE(verbatim_relevance, 0);
+ // Keep pointers to the head of (the highest scoring elements of)
+ // |suggest_results| and |navigation_results|. Iterate down the lists
+ // removing non-inlineable results in order of decreasing relevance
+ // scores. Stop when the highest scoring element among those remaining
+ // is inlineable or the element is less than |verbatim_relevance|.
+ // This allows non-inlineable lower-scoring results to remain
+ // because (i) they are guaranteed to not be inlined and (ii)
+ // letting them remain reduces visual jank. For instance, as the
+ // user types the mis-spelled query "fpobar" (for foobar), the
+ // suggestion "foobar" will be suggested on every keystroke. If the
+ // SearchProvider always removes all non-inlineable results, the user will
+ // see visual jitter/jank as the result disappears and re-appears moments
+ // later as the suggest server returns results.
+ SuggestResults::iterator sug_it = suggest_results->begin();
+ NavigationResults::iterator nav_it = navigation_results->begin();
+ while ((sug_it != suggest_results->end()) ||
+ (nav_it != navigation_results->end())) {
+ const int sug_rel =
+ (sug_it != suggest_results->end()) ? sug_it->relevance() : -1;
+ const int nav_rel =
+ (nav_it != navigation_results->end()) ? nav_it->relevance() : -1;
+ if (std::max(sug_rel, nav_rel) < verbatim_relevance)
+ break;
+ if (sug_rel > nav_rel) {
+ // The current top result is a search suggestion.
+ if (sug_it->IsInlineable(input))
+ break;
+ sug_it = suggest_results->erase(sug_it);
+ } else if (sug_rel == nav_rel) {
+ // Have both results and they're tied.
+ const bool sug_inlineable = sug_it->IsInlineable(input);
+ const bool nav_inlineable = nav_it->IsInlineable(input);
+ if (!sug_inlineable)
+ sug_it = suggest_results->erase(sug_it);
+ if (!nav_inlineable)
+ nav_it = navigation_results->erase(nav_it);
+ if (sug_inlineable || nav_inlineable)
+ break;
+ } else {
+ // The current top result is a navigational suggestion.
+ if (nav_it->IsInlineable(input))
+ break;
+ nav_it = navigation_results->erase(nav_it);
+ }
+ }
+}
+
+// static
+int SearchProvider::CalculateRelevanceForKeywordVerbatim(
+ AutocompleteInput::Type type,
+ bool prefer_keyword) {
+ // This function is responsible for scoring verbatim query matches
+ // for non-extension keywords. KeywordProvider::CalculateRelevance()
+ // scores verbatim query matches for extension keywords, as well as
+ // for keyword matches (i.e., suggestions of a keyword itself, not a
+ // suggestion of a query on a keyword search engine). These two
+ // functions are currently in sync, but there's no reason we
+ // couldn't decide in the future to score verbatim matches
+ // differently for extension and non-extension keywords. If you
+ // make such a change, however, you should update this comment to
+ // describe it, so it's clear why the functions diverge.
+ if (prefer_keyword)
+ return 1500;
+ return (type == AutocompleteInput::QUERY) ? 1450 : 1100;
+}
+
void SearchProvider::Start(const AutocompleteInput& input,
bool minimal_changes) {
const bool suppress_search_suggestions = suppress_search_suggestions_;
@@ -420,104 +617,6 @@ void SearchProvider::Start(const AutocompleteInput& input,
UpdateMatches();
}
-SearchProvider::Result::Result(bool from_keyword_provider, int relevance)
- : from_keyword_provider_(from_keyword_provider),
- relevance_(relevance) {
-}
-
-SearchProvider::Result::~Result() {}
-
-SearchProvider::SuggestResult::SuggestResult(const string16& suggestion,
- bool from_keyword_provider,
- int relevance)
- : Result(from_keyword_provider, relevance),
- suggestion_(suggestion) {
-}
-
-SearchProvider::SuggestResult::~SuggestResult() {}
-
-bool SearchProvider::SuggestResult::IsInlineable(const string16& input) const {
- return StartsWith(suggestion_, input, false);
-}
-
-int SearchProvider::SuggestResult::CalculateRelevance(
- const AutocompleteInput& input,
- bool keyword_provider_requested) const {
- if (!from_keyword_provider_ && keyword_provider_requested)
- return 100;
- return ((input.type() == AutocompleteInput::URL) ? 300 : 600);
-}
-
-SearchProvider::NavigationResult::NavigationResult(
- const AutocompleteProvider& provider,
- const GURL& url,
- const string16& description,
- bool from_keyword_provider,
- int relevance)
- : Result(from_keyword_provider, relevance),
- url_(url),
- formatted_url_(AutocompleteInput::FormattedStringWithEquivalentMeaning(
- url, provider.StringForURLDisplay(url, true, false))),
- description_(description) {
- DCHECK(url_.is_valid());
-}
-
-SearchProvider::NavigationResult::~NavigationResult() {}
-
-bool SearchProvider::NavigationResult::IsInlineable(
- const string16& input) const {
- return URLPrefix::BestURLPrefix(formatted_url_, input) != NULL;
-}
-
-int SearchProvider::NavigationResult::CalculateRelevance(
- const AutocompleteInput& input,
- bool keyword_provider_requested) const {
- return (from_keyword_provider_ || !keyword_provider_requested) ? 800 : 150;
-}
-
-SearchProvider::Results::Results()
- : has_suggested_relevance(false),
- verbatim_relevance(-1) {
-}
-
-SearchProvider::Results::~Results() {
-}
-
-void SearchProvider::Results::Clear() {
- suggest_results.clear();
- navigation_results.clear();
- has_suggested_relevance = false;
- verbatim_relevance = -1;
-}
-
-class SearchProvider::CompareScoredResults {
- public:
- bool operator()(const Result& a, const Result& b) {
- // Sort in descending relevance order.
- return a.relevance() > b.relevance();
- }
-};
-
-void SearchProvider::Run() {
- // Start a new request with the current input.
- suggest_results_pending_ = 0;
- time_suggest_request_sent_ = base::TimeTicks::Now();
-
- default_fetcher_.reset(CreateSuggestFetcher(kDefaultProviderURLFetcherID,
- providers_.GetDefaultProviderURL(), input_));
- keyword_fetcher_.reset(CreateSuggestFetcher(kKeywordProviderURLFetcherID,
- providers_.GetKeywordProviderURL(), keyword_input_));
-
- // Both the above can fail if the providers have been modified or deleted
- // since the query began.
- if (suggest_results_pending_ == 0) {
- UpdateDone();
- // We only need to update the listener if we're actually done.
- if (done_)
- listener_->OnProviderUpdate(false);
- }
-}
-
void SearchProvider::Stop(bool clear_cached_results) {
StopSuggest();
done_ = true;
@@ -527,27 +626,6 @@ void SearchProvider::Stop(bool clear_cached_results) {
ClearAllResults();
}
-void SearchProvider::AddProviderInfo(ProvidersInfo* provider_info) const {
- provider_info->push_back(metrics::OmniboxEventProto_ProviderInfo());
- metrics::OmniboxEventProto_ProviderInfo& new_entry = provider_info->back();
- new_entry.set_provider(AsOmniboxEventProviderType());
- new_entry.set_provider_done(done_);
- std::vector<uint32> field_trial_hashes;
- OmniboxFieldTrial::GetActiveSuggestFieldTrialHashes(&field_trial_hashes);
- for (size_t i = 0; i < field_trial_hashes.size(); ++i) {
- if (field_trial_triggered_)
- new_entry.mutable_field_trial_triggered()->Add(field_trial_hashes[i]);
- if (field_trial_triggered_in_session_) {
- new_entry.mutable_field_trial_triggered_in_session()->Add(
- field_trial_hashes[i]);
- }
- }
-}
-
-void SearchProvider::ResetSession() {
- field_trial_triggered_in_session_ = false;
-}
-
void SearchProvider::OnURLFetchComplete(const net::URLFetcher* source) {
DCHECK(!done_);
suggest_results_pending_--;
@@ -576,9 +654,10 @@ void SearchProvider::OnURLFetchComplete(const net::URLFetcher* source) {
// Ensure the request succeeded and that the provider used is still available.
// A verbatim match cannot be generated without this provider, causing errors.
const bool request_succeeded =
- source->GetStatus().is_success() && source->GetResponseCode() == 200 &&
- ((is_keyword && providers_.GetKeywordProviderURL()) ||
- (!is_keyword && providers_.GetDefaultProviderURL()));
+ source->GetStatus().is_success() && (source->GetResponseCode() == 200) &&
+ (is_keyword ?
+ providers_.GetKeywordProviderURL() :
+ providers_.GetDefaultProviderURL());
// Record response time for suggest requests sent to Google. We care
// only about the common case: the Google default provider used in
@@ -587,7 +666,7 @@ void SearchProvider::OnURLFetchComplete(const net::URLFetcher* source) {
if (!is_keyword && default_url &&
(TemplateURLPrepopulateData::GetEngineType(default_url->url()) ==
SEARCH_ENGINE_GOOGLE)) {
- const TimeDelta elapsed_time =
+ const base::TimeDelta elapsed_time =
base::TimeTicks::Now() - time_suggest_request_sent_;
if (request_succeeded) {
UMA_HISTOGRAM_TIMES("Omnibox.SuggestRequest.Success.GoogleResponseTime",
@@ -611,11 +690,24 @@ void SearchProvider::OnURLFetchComplete(const net::URLFetcher* source) {
listener_->OnProviderUpdate(results_updated);
}
-bool SearchProvider::IsNonInstantSearchDone() const {
- return !timer_.IsRunning() && (suggest_results_pending_ == 0);
-}
+void SearchProvider::Run() {
+ // Start a new request with the current input.
+ suggest_results_pending_ = 0;
+ time_suggest_request_sent_ = base::TimeTicks::Now();
-SearchProvider::~SearchProvider() {
+ default_fetcher_.reset(CreateSuggestFetcher(kDefaultProviderURLFetcherID,
+ providers_.GetDefaultProviderURL(), input_));
+ keyword_fetcher_.reset(CreateSuggestFetcher(kKeywordProviderURLFetcherID,
+ providers_.GetKeywordProviderURL(), keyword_input_));
+
+ // Both the above can fail if the providers have been modified or deleted
+ // since the query began.
+ if (suggest_results_pending_ == 0) {
+ UpdateDone();
+ // We only need to update the listener if we're actually done.
+ if (done_)
+ listener_->OnProviderUpdate(false);
+ }
}
void SearchProvider::DoHistoryQuery(bool minimal_changes) {
@@ -688,7 +780,7 @@ void SearchProvider::StartOrStopSuggestQuery(bool minimal_changes) {
// To avoid flooding the suggest server, don't send a query until at
// least 100 ms since the last query.
base::TimeTicks next_suggest_time(time_suggest_request_sent_ +
- TimeDelta::FromMilliseconds(kMinimumTimeBetweenSuggestQueriesMs));
+ base::TimeDelta::FromMilliseconds(kMinimumTimeBetweenSuggestQueriesMs));
base::TimeTicks now(base::TimeTicks::Now());
if (now >= next_suggest_time) {
Run();
@@ -791,69 +883,13 @@ void SearchProvider::RemoveAllStaleResults() {
}
}
-// static
-void SearchProvider::RemoveStaleResults(const string16& input,
- int verbatim_relevance,
- SuggestResults* suggest_results,
- NavigationResults* navigation_results) {
- DCHECK_GE(verbatim_relevance, 0);
- // Keep pointers to the head of (the highest scoring elements of)
- // |suggest_results| and |navigation_results|. Iterate down the lists
- // removing non-inlineable results in order of decreasing relevance
- // scores. Stop when the highest scoring element among those remaining
- // is inlineable or the element is less than |verbatim_relevance|.
- // This allows non-inlineable lower-scoring results to remain
- // because (i) they are guaranteed to not be inlined and (ii)
- // letting them remain reduces visual jank. For instance, as the
- // user types the mis-spelled query "fpobar" (for foobar), the
- // suggestion "foobar" will be suggested on every keystroke. If the
- // SearchProvider always removes all non-inlineable results, the user will
- // see visual jitter/jank as the result disappears and re-appears moments
- // later as the suggest server returns results.
- SuggestResults::iterator sug_it = suggest_results->begin();
- NavigationResults::iterator nav_it = navigation_results->begin();
- while ((sug_it != suggest_results->end()) ||
- (nav_it != navigation_results->end())) {
- const int sug_rel =
- (sug_it != suggest_results->end()) ? sug_it->relevance() : -1;
- const int nav_rel =
- (nav_it != navigation_results->end()) ? nav_it->relevance() : -1;
- if (std::max(sug_rel, nav_rel) < verbatim_relevance)
- break;
- if (sug_rel > nav_rel) {
- // The current top result is a search suggestion.
- if (sug_it->IsInlineable(input))
- break;
- sug_it = suggest_results->erase(sug_it);
- } else if (sug_rel == nav_rel) {
- // Have both results and they're tied.
- const bool sug_inlineable = sug_it->IsInlineable(input);
- const bool nav_inlineable = nav_it->IsInlineable(input);
- if (!sug_inlineable)
- sug_it = suggest_results->erase(sug_it);
- if (!nav_inlineable)
- nav_it = navigation_results->erase(nav_it);
- if (sug_inlineable || nav_inlineable)
- break;
- } else {
- // The current top result is a navigational suggestion.
- if (nav_it->IsInlineable(input))
- break;
- nav_it = navigation_results->erase(nav_it);
- }
- }
-}
-
void SearchProvider::AdjustDefaultProviderSuggestion(
const string16& previous_input,
const string16& current_input) {
if (default_provider_suggestion_.type == INSTANT_SUGGESTION_URL) {
// Description and relevance do not matter in the check for staleness.
- NavigationResult result(*this,
- GURL(default_provider_suggestion_.text),
- string16(),
- false,
- 100);
+ NavigationResult result(*this, GURL(default_provider_suggestion_.text),
+ string16(), false, 100);
// If navigation suggestion is stale, clear |default_provider_suggestion_|.
if (!result.IsInlineable(current_input))
default_provider_suggestion_ = InstantSuggestion();
@@ -1038,7 +1074,7 @@ void SearchProvider::ConvertResultsToAutocompleteMatches() {
// Convert all the results to matches and add them to a map, so we can keep
// the most relevant match for each result.
MatchMap map;
- const Time no_time;
+ const base::Time no_time;
int did_not_accept_keyword_suggestion =
keyword_results_.suggest_results.empty() ?
TemplateURLRef::NO_SUGGESTIONS_AVAILABLE :
@@ -1099,15 +1135,12 @@ void SearchProvider::ConvertResultsToAutocompleteMatches() {
!input_.prevent_inline_autocomplete()) {
// See comment in FinalizeInstantQuery() for why we don't use
// |verbatim_relevance| here.
- matches_.push_back(NavigationToMatch(
- NavigationResult(*this,
- GURL(UTF16ToUTF8(default_provider_suggestion_.text)),
- string16(),
- false,
- kNonURLVerbatimRelevance + 1)));
+ matches_.push_back(NavigationToMatch(NavigationResult(
+ *this, GURL(UTF16ToUTF8(default_provider_suggestion_.text)), string16(),
+ false, kNonURLVerbatimRelevance + 1)));
}
- AddNavigationResultsToMatches(keyword_results_.navigation_results, true);
- AddNavigationResultsToMatches(default_results_.navigation_results, false);
+ AddNavigationResultsToMatches(keyword_results_.navigation_results);
+ AddNavigationResultsToMatches(default_results_.navigation_results);
// Allow additional match(es) for verbatim results if present.
const size_t max_total_matches = kMaxMatches + verbatim_matches_size;
@@ -1164,10 +1197,8 @@ void SearchProvider::UpdateMatches() {
// Check constraints that may be violated by suggested relevances.
if (!matches_.empty() &&
- (default_results_.has_suggested_relevance ||
- default_results_.verbatim_relevance >= 0 ||
- keyword_results_.has_suggested_relevance ||
- keyword_results_.verbatim_relevance >= 0)) {
+ (default_results_.HasServerProvidedScores() ||
+ keyword_results_.HasServerProvidedScores())) {
// These blocks attempt to repair undesirable behavior by suggested
// relevances with minimal impact, preserving other suggested relevances.
if (IsTopMatchNavigationInKeywordMode()) {
@@ -1223,23 +1254,16 @@ void SearchProvider::UpdateMatches() {
}
void SearchProvider::AddNavigationResultsToMatches(
- const NavigationResults& navigation_results,
- bool is_keyword) {
- if (navigation_results.empty())
- return;
-
- if (is_keyword ?
- keyword_results_.has_suggested_relevance :
- default_results_.has_suggested_relevance) {
- for (NavigationResults::const_iterator it = navigation_results.begin();
- it != navigation_results.end(); ++it)
- matches_.push_back(NavigationToMatch(*it));
- } else {
- // Pick the highest-scoring element only in absence of the
- // suggested relevance scores. (The results are already sorted.)
- // TODO(kochi|msw): Add more navigational results if they get more
- // meaningful relevance values; see http://b/1170574.
- matches_.push_back(NavigationToMatch(navigation_results.front()));
+ const NavigationResults& navigation_results) {
+ for (NavigationResults::const_iterator it = navigation_results.begin();
+ it != navigation_results.end(); ++it) {
+ matches_.push_back(NavigationToMatch(*it));
+ // In the absence of suggested relevance scores, use only the single
+ // highest-scoring result. (The results are already sorted by relevance.)
+ if (!(it->from_keyword_provider() ?
+ keyword_results_.has_suggested_relevance :
+ default_results_.has_suggested_relevance))
+ return;
}
}
@@ -1363,14 +1387,14 @@ int SearchProvider::GetVerbatimRelevance() const {
// left unable to search using their default provider from the omnibox.
// Check for results on each verbatim calculation, as results from older
// queries (on previous input) may be trimmed for failing to inline new input.
- if (default_results_.verbatim_relevance >= 0 &&
+ bool use_server_relevance =
+ (default_results_.verbatim_relevance >= 0) &&
!input_.prevent_inline_autocomplete() &&
- (default_results_.verbatim_relevance > 0 ||
+ ((default_results_.verbatim_relevance > 0) ||
!default_results_.suggest_results.empty() ||
- !default_results_.navigation_results.empty())) {
- return default_results_.verbatim_relevance;
- }
- return CalculateRelevanceForVerbatim();
+ !default_results_.navigation_results.empty());
+ return use_server_relevance ?
+ default_results_.verbatim_relevance : CalculateRelevanceForVerbatim();
}
int SearchProvider::CalculateRelevanceForVerbatim() const {
@@ -1405,38 +1429,20 @@ int SearchProvider::GetKeywordVerbatimRelevance() const {
// left unable to search using their keyword provider from the omnibox.
// Check for results on each verbatim calculation, as results from older
// queries (on previous input) may be trimmed for failing to inline new input.
- if (keyword_results_.verbatim_relevance >= 0 &&
+ bool use_server_relevance =
+ (keyword_results_.verbatim_relevance >= 0) &&
!input_.prevent_inline_autocomplete() &&
- (keyword_results_.verbatim_relevance > 0 ||
+ ((keyword_results_.verbatim_relevance > 0) ||
!keyword_results_.suggest_results.empty() ||
- !keyword_results_.navigation_results.empty())) {
- return keyword_results_.verbatim_relevance;
- }
- return CalculateRelevanceForKeywordVerbatim(
- keyword_input_.type(), keyword_input_.prefer_keyword());
-}
-
-// static
-int SearchProvider::CalculateRelevanceForKeywordVerbatim(
- AutocompleteInput::Type type,
- bool prefer_keyword) {
- // This function is responsible for scoring verbatim query matches
- // for non-extension keywords. KeywordProvider::CalculateRelevance()
- // scores verbatim query matches for extension keywords, as well as
- // for keyword matches (i.e., suggestions of a keyword itself, not a
- // suggestion of a query on a keyword search engine). These two
- // functions are currently in sync, but there's no reason we
- // couldn't decide in the future to score verbatim matches
- // differently for extension and non-extension keywords. If you
- // make such a change, however, you should update this comment to
- // describe it, so it's clear why the functions diverge.
- if (prefer_keyword)
- return 1500;
- return (type == AutocompleteInput::QUERY) ? 1450 : 1100;
+ !keyword_results_.navigation_results.empty());
+ return use_server_relevance ?
+ keyword_results_.verbatim_relevance :
+ CalculateRelevanceForKeywordVerbatim(keyword_input_.type(),
+ keyword_input_.prefer_keyword());
}
int SearchProvider::CalculateRelevanceForHistory(
- const Time& time,
+ const base::Time& time,
bool is_keyword,
bool prevent_inline_autocomplete) const {
// The relevance of past searches falls off over time. There are two distinct
@@ -1445,7 +1451,7 @@ int SearchProvider::CalculateRelevanceForHistory(
// 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.);
+ double elapsed_time = std::max((base::Time::Now() - time).InSecondsF(), 0.0);
bool is_primary_provider = is_keyword || !providers_.has_keyword_provider();
if (is_primary_provider && !prevent_inline_autocomplete) {
// Searches with the past two days get a different curve.
@@ -1481,6 +1487,11 @@ void SearchProvider::AddMatchToMap(const string16& query_string,
// -- they should always use grey text if they are to autocomplete at all. So
// we clamp non-verbatim results to just below the verbatim score to ensure
// that none of them are inline autocompleted.
+ // TODO(pkasting): This shouldn't depend on instant extended. If we think
+ // this change is a win, let's change the suggest server to not send
+ // high-ranking suggest scores, and change CalculateRelevanceForHistory() to
+ // use lower curves. This code is also buggy as-is because it can demote many
+ // matches to the same relevance score.
if (type != AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED &&
type != AutocompleteMatchType::SEARCH_OTHER_ENGINE &&
chrome::IsInstantExtendedAPIEnabled()) {
@@ -1498,9 +1509,8 @@ void SearchProvider::AddMatchToMap(const string16& query_string,
// Try to add |match| to |map|. If a match for |query_string| is already in
// |map|, replace it if |match| is more relevant.
// NOTE: Keep this ToLower() call in sync with url_database.cc.
- const std::pair<MatchMap::iterator, bool> i = map->insert(
- std::pair<string16, AutocompleteMatch>(
- base::i18n::ToLower(query_string), match));
+ const std::pair<MatchMap::iterator, bool> i(
+ map->insert(std::make_pair(base::i18n::ToLower(query_string), match)));
// NOTE: We purposefully do a direct relevance comparison here instead of
// using AutocompleteMatch::MoreRelevant(), so that we'll prefer "items added
// first" rather than "items alphabetically first" when the scores are equal.
diff --git a/chrome/browser/autocomplete/search_provider.h b/chrome/browser/autocomplete/search_provider.h
index 1251402..e4400fd 100644
--- a/chrome/browser/autocomplete/search_provider.h
+++ b/chrome/browser/autocomplete/search_provider.h
@@ -59,6 +59,8 @@ class SearchProvider : public AutocompleteProvider,
// ID used in creating URLFetcher for keyword provider's suggest results.
static const int kKeywordProviderURLFetcherID;
+ SearchProvider(AutocompleteProviderListener* listener, Profile* profile);
+
// Returns an AutocompleteMatch representing a search for |query_string|
// using the provider identified by |keyword|. |is_keyword| should be true if
// |input| represents a keyword search (even if it's for the default search
@@ -78,7 +80,9 @@ class SearchProvider : public AutocompleteProvider,
const string16& keyword,
int omnibox_start_margin);
- SearchProvider(AutocompleteProviderListener* listener, Profile* profile);
+ // AutocompleteProvider:
+ virtual void AddProviderInfo(ProvidersInfo* provider_info) const OVERRIDE;
+ virtual void ResetSession() OVERRIDE;
// Marks the instant query as done. If |input_text| is non-empty this changes
// the 'search what you typed' results text to |input_text| +
@@ -104,20 +108,6 @@ class SearchProvider : public AutocompleteProvider,
// Update the omnibox start margin used to generate search suggestion URLs.
void SetOmniboxStartMargin(int omnibox_start_margin);
- // AutocompleteProvider:
- virtual void Start(const AutocompleteInput& input,
- bool minimal_changes) OVERRIDE;
- virtual void Stop(bool clear_cached_results) OVERRIDE;
-
- // Adds search-provider-specific information to omnibox event logs.
- virtual void AddProviderInfo(ProvidersInfo* provider_info) const OVERRIDE;
-
- // Sets |field_trial_triggered_in_session_| to false.
- virtual void ResetSession() OVERRIDE;
-
- // net::URLFetcherDelegate
- virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE;
-
// Returns whether the provider is done processing the query with the
// exception of waiting for Instant to finish.
bool IsNonInstantSearchDone() const;
@@ -138,12 +128,6 @@ class SearchProvider : public AutocompleteProvider,
FRIEND_TEST_ALL_PREFIXES(SearchProviderTest, SuggestRelevanceExperiment);
FRIEND_TEST_ALL_PREFIXES(AutocompleteProviderTest, GetDestinationURL);
- // The amount of time to wait before sending a new suggest request after
- // the previous one.
- static int kMinimumTimeBetweenSuggestQueriesMs;
-
- virtual ~SearchProvider();
-
// Manages the providers (TemplateURLs) used by SearchProvider. Two providers
// may be used:
// . The default provider. This corresponds to the user's default search
@@ -200,9 +184,7 @@ class SearchProvider : public AutocompleteProvider,
// highly fragmented SearchProvider logic for each Result type.
class Result {
public:
- // Takes whether the result is from the keyword provider and its
- // assigned relevance score.
- explicit Result(bool from_keyword_provider, int relevance);
+ Result(bool from_keyword_provider, int relevance);
virtual ~Result();
bool from_keyword_provider() const { return from_keyword_provider_; }
@@ -262,9 +244,7 @@ class SearchProvider : public AutocompleteProvider,
const GURL& url() const { return url_; }
const string16& description() const { return description_; }
- const string16& formatted_url() const {
- return formatted_url_;
- }
+ const string16& formatted_url() const { return formatted_url_; }
// Result:
virtual bool IsInlineable(const string16& input) const OVERRIDE;
@@ -284,12 +264,18 @@ class SearchProvider : public AutocompleteProvider,
string16 description_;
};
+ class CompareScoredResults;
+
typedef std::vector<SuggestResult> SuggestResults;
typedef std::vector<NavigationResult> NavigationResults;
+ typedef std::vector<history::KeywordSearchTermVisit> HistoryResults;
+ typedef std::map<string16, AutocompleteMatch> MatchMap;
// A simple structure bundling most of the information (including
// both SuggestResults and NavigationResults) returned by a call to
// the suggest server.
+ //
+ // This has to be declared after the typedefs since it relies on some of them.
struct Results {
Results();
~Results();
@@ -299,6 +285,10 @@ class SearchProvider : public AutocompleteProvider,
// values (false and -1 (implies unset), respectively).
void Clear();
+ // Returns whether any of the results (including verbatim) have
+ // server-provided scores.
+ bool HasServerProvidedScores() const;
+
// Query suggestions sorted by relevance score.
SuggestResults suggest_results;
@@ -317,10 +307,27 @@ class SearchProvider : public AutocompleteProvider,
DISALLOW_COPY_AND_ASSIGN(Results);
};
- typedef std::vector<history::KeywordSearchTermVisit> HistoryResults;
- typedef std::map<string16, AutocompleteMatch> MatchMap;
+ virtual ~SearchProvider();
- class CompareScoredResults;
+ // Removes non-inlineable results until either the top result can inline
+ // autocomplete the current input or verbatim outscores the top result.
+ static void RemoveStaleResults(const string16& input,
+ int verbatim_relevance,
+ SuggestResults* suggest_results,
+ NavigationResults* navigation_results);
+
+ // Calculates the relevance score for the keyword verbatim result (if the
+ // input matches one of the profile's keyword).
+ static int CalculateRelevanceForKeywordVerbatim(AutocompleteInput::Type type,
+ bool prefer_keyword);
+
+ // AutocompleteProvider:
+ virtual void Start(const AutocompleteInput& input,
+ bool minimal_changes) OVERRIDE;
+ virtual void Stop(bool clear_cached_results) OVERRIDE;
+
+ // net::URLFetcherDelegate:
+ virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE;
// Called when timer_ expires.
void Run();
@@ -346,13 +353,9 @@ class SearchProvider : public AutocompleteProvider,
// Clears the current results.
void ClearAllResults();
- // Removes non-inlineable results until either the top result can inline
- // autocomplete the current input or verbatim outscores the top result.
+ // Removes stale results for both default and keyword providers. See comments
+ // on RemoveStaleResults().
void RemoveAllStaleResults();
- static void RemoveStaleResults(const string16& input,
- int verbatim_relevance,
- SuggestResults* suggest_results,
- NavigationResults* navigation_results);
// If |default_provider_suggestion_| (which was suggested for
// |previous_input|) is still applicable given the |current_input|, adjusts it
@@ -390,12 +393,10 @@ class SearchProvider : public AutocompleteProvider,
// if suggested relevances cause undesriable behavior. Updates |done_|.
void UpdateMatches();
- // Converts the top navigation result in |navigation_results| to an
- // AutocompleteMatch and adds it to |matches_|. |is_keyword| must be true if
- // the results come from the keyword provider.
+ // Converts an appropriate number of navigation results in
+ // |navigation_results| to matches and adds them to |matches_|.
void AddNavigationResultsToMatches(
- const NavigationResults& navigation_results,
- bool is_keyword);
+ const NavigationResults& navigation_results);
// Adds a match for each result in |results| to |map|. |is_keyword| indicates
// whether the results correspond to the keyword provider or default provider.
@@ -414,30 +415,28 @@ class SearchProvider : public AutocompleteProvider,
// Adds matches for |results| to |map|.
void AddSuggestResultsToMap(const SuggestResults& results, MatchMap* map);
- // Gets the relevance score for the verbatim result; this value may be
- // provided by the suggest server; otherwise it is calculated locally.
+ // Gets the relevance score for the verbatim result. This value may be
+ // provided by the suggest server or calculated locally.
int GetVerbatimRelevance() const;
+
// Calculates the relevance score for the verbatim result from the
// default search engine. This version takes into account context:
// i.e., whether the user has entered a keyword-based search or not.
int CalculateRelevanceForVerbatim() const;
+
// Calculates the relevance score for the verbatim result from the default
// search engine *ignoring* whether the input is a keyword-based search
// or not. This function should only be used to determine the minimum
// relevance score that the best result from this provider should have.
// For normal use, prefer the above function.
int CalculateRelevanceForVerbatimIgnoringKeywordModeState() const;
- // Gets the relevance score for the keyword verbatim result; this
- // value may be provided by the suggest server; otherwise it is
- // calculated locally.
+
+ // Gets the relevance score for the keyword verbatim result.
// TODO(mpearson): Refactor so this duplication isn't necesary or
// restructure so one static function takes all the parameters it needs
// (rather than looking at internal state).
int GetKeywordVerbatimRelevance() const;
- // Calculates the relevance score for the keyword verbatim result (if the
- // input matches one of the profile's keyword).
- static int CalculateRelevanceForKeywordVerbatim(AutocompleteInput::Type type,
- bool prefer_keyword);
+
// |time| is the time at which this query was last seen. |is_keyword|
// indicates whether the results correspond to the keyword provider or default
// provider. |prevent_inline_autocomplete| is true if we should not inline
@@ -473,6 +472,10 @@ class SearchProvider : public AutocompleteProvider,
// Updates the value of |done_| from the internal state.
void UpdateDone();
+ // The amount of time to wait before sending a new suggest request after the
+ // previous one. Non-const because some unittests modify this value.
+ static int kMinimumTimeBetweenSuggestQueriesMs;
+
// Maintains the TemplateURLs used.
Providers providers_;
diff --git a/chrome/browser/autocomplete/search_provider_unittest.cc b/chrome/browser/autocomplete/search_provider_unittest.cc
index 88edef6..6d244b8 100644
--- a/chrome/browser/autocomplete/search_provider_unittest.cc
+++ b/chrome/browser/autocomplete/search_provider_unittest.cc
@@ -51,9 +51,9 @@ class SearchProviderTest : public testing::Test,
public:
SearchProviderTest()
: default_t_url_(NULL),
- term1_(UTF8ToUTF16("term1")),
+ term1_(ASCIIToUTF16("term1")),
keyword_t_url_(NULL),
- keyword_term_(UTF8ToUTF16("keyword")),
+ keyword_term_(ASCIIToUTF16("keyword")),
ui_thread_(BrowserThread::UI, &message_loop_),
io_thread_(BrowserThread::IO),
quit_when_done_(false) {
@@ -438,7 +438,7 @@ TEST_F(SearchProviderTest, HonorPreventInlineAutocomplete) {
// is queried as well as URLFetchers getting created.
TEST_F(SearchProviderTest, QueryKeywordProvider) {
string16 term = keyword_term_.substr(0, keyword_term_.length() - 1);
- QueryForInput(keyword_t_url_->keyword() + UTF8ToUTF16(" ") + term,
+ QueryForInput(keyword_t_url_->keyword() + ASCIIToUTF16(" ") + term,
false,
false);
@@ -1201,7 +1201,7 @@ TEST_F(SearchProviderTest, DefaultFetcherSuggestRelevance) {
fetcher->delegate()->OnURLFetchComplete(fetcher);
RunTillProviderDone();
- const std::string description = "for input with json=" + cases[i].json;
+ const std::string description = "for input with json=" + cases[i].json;
const ACMatches& matches = provider_->matches();
// The top match must inline and score as highly as calculated verbatim.
EXPECT_NE(string16::npos, matches[0].inline_autocomplete_offset) <<
@@ -1571,8 +1571,7 @@ TEST_F(SearchProviderTest, KeywordFetcherSuggestRelevance) {
// we abandon suggested relevance scores entirely. One consequence is
// that this means we restore the keyword verbatim match. Note
// that in this case of abandoning suggested relevance scores, we still
- // keep the navsuggestions in order by their original scores (just
- // not at their original scores), and continue to allow multiple
+ // keep the navsuggestions in the same order, and continue to allow multiple
// navsuggestions to appear.
{ "[\"a\",[\"http://a1.com\", \"http://a2.com\"],[],[],"
"{\"google:suggesttype\":[\"NAVIGATION\", \"NAVIGATION\"],"
@@ -1928,9 +1927,9 @@ TEST_F(SearchProviderTest, NavigationInline) {
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); i++) {
QueryForInput(ASCIIToUTF16(cases[i].input), false, false);
- SearchProvider::NavigationResult result(
- *provider_.get(), GURL(cases[i].url), string16(), false, 0);
- AutocompleteMatch match(provider_->NavigationToMatch(result));
+ AutocompleteMatch match(
+ provider_->NavigationToMatch(SearchProvider::NavigationResult(
+ *provider_.get(), GURL(cases[i].url), string16(), false, 0)));
EXPECT_EQ(cases[i].inline_offset, match.inline_autocomplete_offset);
EXPECT_EQ(ASCIIToUTF16(cases[i].fill_into_edit), match.fill_into_edit);
}
@@ -1961,10 +1960,9 @@ TEST_F(SearchProviderTest, NavigationInlineSchemeSubstring) {
// Verifies that input "w" marks a more significant domain label than "www.".
TEST_F(SearchProviderTest, NavigationInlineDomainClassify) {
QueryForInput(ASCIIToUTF16("w"), false, false);
- const GURL url("http://www.wow.com");
- const SearchProvider::NavigationResult result(
- *provider_.get(), url, string16(), false, 0);
- AutocompleteMatch match(provider_->NavigationToMatch(result));
+ AutocompleteMatch match(
+ provider_->NavigationToMatch(SearchProvider::NavigationResult(
+ *provider_.get(), GURL("http://www.wow.com"), string16(), false, 0)));
EXPECT_EQ(5U, match.inline_autocomplete_offset);
EXPECT_EQ(ASCIIToUTF16("www.wow.com"), match.fill_into_edit);
EXPECT_EQ(ASCIIToUTF16("www.wow.com"), match.contents);
@@ -2124,11 +2122,9 @@ TEST_F(SearchProviderTest, RemoveStaleResultsTest) {
break;
if (cases[i].results[j].is_navigation_result) {
provider_->default_results_.navigation_results.push_back(
- SearchProvider::NavigationResult(*provider_.get(),
- GURL(suggestion),
- string16(),
- false,
- cases[i].results[j].relevance));
+ SearchProvider::NavigationResult(
+ *provider_.get(), GURL(suggestion), string16(), false,
+ cases[i].results[j].relevance));
} else {
provider_->default_results_.suggest_results.push_back(
SearchProvider::SuggestResult(ASCIIToUTF16(suggestion), false,
diff --git a/chrome/browser/autocomplete/zero_suggest_provider.cc b/chrome/browser/autocomplete/zero_suggest_provider.cc
index b210f5a..6cc2fd5 100644
--- a/chrome/browser/autocomplete/zero_suggest_provider.cc
+++ b/chrome/browser/autocomplete/zero_suggest_provider.cc
@@ -335,9 +335,8 @@ void ZeroSuggestProvider::AddMatchToMap(const string16& query_string,
// Try to add |match| to |map|. If a match for |query_string| is already in
// |map|, replace it if |match| is more relevant.
// NOTE: Keep this ToLower() call in sync with url_database.cc.
- const std::pair<SearchProvider::MatchMap::iterator, bool> i = map->insert(
- std::pair<string16, AutocompleteMatch>(
- base::i18n::ToLower(query_string), match));
+ const std::pair<SearchProvider::MatchMap::iterator, bool> i(map->insert(
+ std::make_pair(base::i18n::ToLower(query_string), match)));
// NOTE: We purposefully do a direct relevance comparison here instead of
// using AutocompleteMatch::MoreRelevant(), so that we'll prefer "items added
// first" rather than "items alphabetically first" when the scores are equal.
@@ -462,16 +461,13 @@ void ZeroSuggestProvider::ConvertResultsToAutocompleteMatches(
0 : string16::npos;
matches_.push_back(current_url_match_);
- for (SearchProvider::MatchMap::const_iterator it = query_matches_map_.begin();
- it != query_matches_map_.end(); ++it) {
+ for (SearchProvider::MatchMap::const_iterator it(query_matches_map_.begin());
+ it != query_matches_map_.end(); ++it)
matches_.push_back(it->second);
- }
- for (SearchProvider::NavigationResults::const_iterator it =
- navigation_results_.begin();
- it != navigation_results_.end(); ++it) {
+ for (SearchProvider::NavigationResults::const_iterator it(
+ navigation_results_.begin()); it != navigation_results_.end(); ++it)
matches_.push_back(NavigationToMatch(*it));
- }
}
AutocompleteMatch ZeroSuggestProvider::MatchForCurrentURL() {