| Index: components/omnibox/search_provider.cc
|
| diff --git a/components/omnibox/search_provider.cc b/components/omnibox/search_provider.cc
|
| index 41763048fb52a74899b507382e64b6f902d82fae..b5a9e41c79deb6988fc91af7c9d6af180a29cfc2 100644
|
| --- a/components/omnibox/search_provider.cc
|
| +++ b/components/omnibox/search_provider.cc
|
| @@ -265,7 +265,26 @@ void SearchProvider::Start(const AutocompleteInput& input,
|
| input_ = input;
|
|
|
| DoHistoryQuery(minimal_changes);
|
| - DoAnswersQuery(input);
|
| + // Answers needs scored history results before any suggest query has been
|
| + // started, since the query for answer-bearing results needs additional
|
| + // prefetch information based on the highest-scored local history result.
|
| + if (OmniboxFieldTrial::EnableAnswersInSuggest()) {
|
| + ScoreHistoryResults(raw_default_history_results_,
|
| + false,
|
| + &transformed_default_history_results_);
|
| + ScoreHistoryResults(raw_keyword_history_results_,
|
| + true,
|
| + &transformed_keyword_history_results_);
|
| + prefetch_data_ = FindAnswersPrefetchData();
|
| +
|
| + // Raw results are not needed any more.
|
| + raw_default_history_results_.clear();
|
| + raw_keyword_history_results_.clear();
|
| + } else {
|
| + transformed_default_history_results_.clear();
|
| + transformed_keyword_history_results_.clear();
|
| + }
|
| +
|
| StartOrStopSuggestQuery(minimal_changes);
|
| UpdateMatches();
|
| }
|
| @@ -519,8 +538,8 @@ void SearchProvider::DoHistoryQuery(bool minimal_changes) {
|
| if (minimal_changes)
|
| return;
|
|
|
| - keyword_history_results_.clear();
|
| - default_history_results_.clear();
|
| + raw_keyword_history_results_.clear();
|
| + raw_default_history_results_.clear();
|
|
|
| if (OmniboxFieldTrial::SearchHistoryDisable(
|
| input_.current_page_classification()))
|
| @@ -533,7 +552,7 @@ void SearchProvider::DoHistoryQuery(bool minimal_changes) {
|
| // Request history for both the keyword and default provider. We grab many
|
| // more matches than we'll ultimately clamp to so that if there are several
|
| // recent multi-word matches who scores are lowered (see
|
| - // AddHistoryResultsToMap()), they won't crowd out older, higher-scoring
|
| + // ScoreHistoryResults()), they won't crowd out older, higher-scoring
|
| // matches. Note that this doesn't fix the problem entirely, but merely
|
| // limits it to cases with a very large number of such multi-word matches; for
|
| // now, this seems OK compared with the complexity of a real fix, which would
|
| @@ -543,8 +562,10 @@ void SearchProvider::DoHistoryQuery(bool minimal_changes) {
|
| const TemplateURL* default_url = providers_.GetDefaultProviderURL();
|
| if (default_url) {
|
| const base::TimeTicks start_time = base::TimeTicks::Now();
|
| - url_db->GetMostRecentKeywordSearchTerms(default_url->id(), input_.text(),
|
| - num_matches, &default_history_results_);
|
| + url_db->GetMostRecentKeywordSearchTerms(default_url->id(),
|
| + input_.text(),
|
| + num_matches,
|
| + &raw_default_history_results_);
|
| UMA_HISTOGRAM_TIMES(
|
| "Omnibox.SearchProvider.GetMostRecentKeywordTermsDefaultProviderTime",
|
| base::TimeTicks::Now() - start_time);
|
| @@ -552,7 +573,9 @@ void SearchProvider::DoHistoryQuery(bool minimal_changes) {
|
| const TemplateURL* keyword_url = providers_.GetKeywordProviderURL();
|
| if (keyword_url) {
|
| url_db->GetMostRecentKeywordSearchTerms(keyword_url->id(),
|
| - keyword_input_.text(), num_matches, &keyword_history_results_);
|
| + keyword_input_.text(),
|
| + num_matches,
|
| + &raw_keyword_history_results_);
|
| }
|
| }
|
|
|
| @@ -844,10 +867,8 @@ void SearchProvider::ConvertResultsToAutocompleteMatches() {
|
| }
|
| }
|
| }
|
| - AddHistoryResultsToMap(keyword_history_results_, true,
|
| - did_not_accept_keyword_suggestion, &map);
|
| - AddHistoryResultsToMap(default_history_results_, false,
|
| - did_not_accept_default_suggestion, &map);
|
| + AddRawHistoryResultsToMap(true, did_not_accept_keyword_suggestion, &map);
|
| + AddRawHistoryResultsToMap(false, did_not_accept_default_suggestion, &map);
|
|
|
| AddSuggestResultsToMap(keyword_results_.suggest_results,
|
| keyword_results_.metadata, &map);
|
| @@ -937,56 +958,56 @@ void SearchProvider::AddNavigationResultsToMatches(
|
| }
|
| }
|
|
|
| -void SearchProvider::AddHistoryResultsToMap(const HistoryResults& results,
|
| - bool is_keyword,
|
| - int did_not_accept_suggestion,
|
| - MatchMap* map) {
|
| - if (results.empty())
|
| +void SearchProvider::AddRawHistoryResultsToMap(bool is_keyword,
|
| + int did_not_accept_suggestion,
|
| + MatchMap* map) {
|
| + const HistoryResults& raw_results =
|
| + is_keyword ? raw_keyword_history_results_ : raw_default_history_results_;
|
| + if (!OmniboxFieldTrial::EnableAnswersInSuggest() && raw_results.empty())
|
| return;
|
|
|
| base::TimeTicks start_time(base::TimeTicks::Now());
|
| - bool prevent_inline_autocomplete = input_.prevent_inline_autocomplete() ||
|
| - (input_.type() == metrics::OmniboxInputType::URL);
|
| - const base::string16& input_text =
|
| - is_keyword ? keyword_input_.text() : input_.text();
|
| - bool input_multiple_words = HasMultipleWords(input_text);
|
|
|
| - SearchSuggestionParser::SuggestResults scored_results;
|
| - if (!prevent_inline_autocomplete && input_multiple_words) {
|
| - // ScoreHistoryResults() allows autocompletion of multi-word, 1-visit
|
| - // queries if the input also has multiple words. But if we were already
|
| - // scoring a multi-word, multi-visit query aggressively, and the current
|
| - // input is still a prefix of it, then changing the suggestion suddenly
|
| - // feels wrong. To detect this case, first score as if only one word has
|
| - // been typed, then check if the best result came from aggressive search
|
| - // history scoring. If it did, then just keep that score set. This
|
| - // 1200 the lowest possible score in CalculateRelevanceForHistory()'s
|
| - // aggressive-scoring curve.
|
| - scored_results = ScoreHistoryResults(results, prevent_inline_autocomplete,
|
| - false, input_text, is_keyword);
|
| - if ((scored_results.front().relevance() < 1200) ||
|
| - !HasMultipleWords(scored_results.front().suggestion()))
|
| - scored_results.clear(); // Didn't detect the case above, score normally.
|
| + // Until Answers becomes default, scoring of history results will still happen
|
| + // here for non-Answers Chrome, to prevent scoring performance regressions
|
| + // resulting from moving the scoring code before the suggest request is sent.
|
| + // For users with Answers enabled, the history results have already been
|
| + // scored earlier, right after calling DoHistoryQuery().
|
| + SearchSuggestionParser::SuggestResults local_transformed_results;
|
| + const SearchSuggestionParser::SuggestResults* transformed_results = NULL;
|
| + if (!OmniboxFieldTrial::EnableAnswersInSuggest()) {
|
| + ScoreHistoryResults(raw_results, is_keyword, &local_transformed_results);
|
| + transformed_results = &local_transformed_results;
|
| + } else {
|
| + transformed_results = is_keyword ? &transformed_keyword_history_results_
|
| + : &transformed_default_history_results_;
|
| }
|
| - if (scored_results.empty())
|
| - scored_results = ScoreHistoryResults(results, prevent_inline_autocomplete,
|
| - input_multiple_words, input_text,
|
| - is_keyword);
|
| + DCHECK(transformed_results);
|
| + AddTransformedHistoryResultsToMap(
|
| + *transformed_results, did_not_accept_suggestion, map);
|
| + UMA_HISTOGRAM_TIMES("Omnibox.SearchProvider.AddHistoryResultsTime",
|
| + base::TimeTicks::Now() - start_time);
|
| +}
|
| +
|
| +void SearchProvider::AddTransformedHistoryResultsToMap(
|
| + const SearchSuggestionParser::SuggestResults& transformed_results,
|
| + int did_not_accept_suggestion,
|
| + MatchMap* map) {
|
| for (SearchSuggestionParser::SuggestResults::const_iterator i(
|
| - scored_results.begin()); i != scored_results.end(); ++i) {
|
| + transformed_results.begin());
|
| + i != transformed_results.end();
|
| + ++i) {
|
| AddMatchToMap(*i, std::string(), did_not_accept_suggestion, true,
|
| providers_.GetKeywordProviderURL() != NULL, map);
|
| }
|
| - UMA_HISTOGRAM_TIMES("Omnibox.SearchProvider.AddHistoryResultsTime",
|
| - base::TimeTicks::Now() - start_time);
|
| }
|
|
|
| -SearchSuggestionParser::SuggestResults SearchProvider::ScoreHistoryResults(
|
| - const HistoryResults& results,
|
| - bool base_prevent_inline_autocomplete,
|
| - bool input_multiple_words,
|
| - const base::string16& input_text,
|
| - bool is_keyword) {
|
| +SearchSuggestionParser::SuggestResults
|
| +SearchProvider::ScoreHistoryResultsHelper(const HistoryResults& results,
|
| + bool base_prevent_inline_autocomplete,
|
| + bool input_multiple_words,
|
| + const base::string16& input_text,
|
| + bool is_keyword) {
|
| SearchSuggestionParser::SuggestResults scored_results;
|
| // True if the user has asked this exact query previously.
|
| bool found_what_you_typed_match = false;
|
| @@ -1092,6 +1113,46 @@ SearchSuggestionParser::SuggestResults SearchProvider::ScoreHistoryResults(
|
| return scored_results;
|
| }
|
|
|
| +void SearchProvider::ScoreHistoryResults(
|
| + const HistoryResults& results,
|
| + bool is_keyword,
|
| + SearchSuggestionParser::SuggestResults* scored_results) {
|
| + DCHECK(scored_results);
|
| + if (results.empty()) {
|
| + scored_results->clear();
|
| + return;
|
| + }
|
| +
|
| + bool prevent_inline_autocomplete = input_.prevent_inline_autocomplete() ||
|
| + (input_.type() == metrics::OmniboxInputType::URL);
|
| + const base::string16 input_text = GetInput(is_keyword).text();
|
| + bool input_multiple_words = HasMultipleWords(input_text);
|
| +
|
| + if (!prevent_inline_autocomplete && input_multiple_words) {
|
| + // ScoreHistoryResultsHelper() allows autocompletion of multi-word, 1-visit
|
| + // queries if the input also has multiple words. But if we were already
|
| + // scoring a multi-word, multi-visit query aggressively, and the current
|
| + // input is still a prefix of it, then changing the suggestion suddenly
|
| + // feels wrong. To detect this case, first score as if only one word has
|
| + // been typed, then check if the best result came from aggressive search
|
| + // history scoring. If it did, then just keep that score set. This
|
| + // 1200 the lowest possible score in CalculateRelevanceForHistory()'s
|
| + // aggressive-scoring curve.
|
| + *scored_results = ScoreHistoryResultsHelper(
|
| + results, prevent_inline_autocomplete, false, input_text, is_keyword);
|
| + if ((scored_results->front().relevance() < 1200) ||
|
| + !HasMultipleWords(scored_results->front().suggestion()))
|
| + scored_results->clear(); // Didn't detect the case above, score normally.
|
| + }
|
| + if (scored_results->empty()) {
|
| + *scored_results = ScoreHistoryResultsHelper(results,
|
| + prevent_inline_autocomplete,
|
| + input_multiple_words,
|
| + input_text,
|
| + is_keyword);
|
| + }
|
| +}
|
| +
|
| void SearchProvider::AddSuggestResultsToMap(
|
| const SearchSuggestionParser::SuggestResults& results,
|
| const std::string& metadata,
|
| @@ -1333,6 +1394,24 @@ void SearchProvider::RegisterDisplayedAnswers(
|
| answers_cache_.UpdateRecentAnswers(match->fill_into_edit, match->answer_type);
|
| }
|
|
|
| -void SearchProvider::DoAnswersQuery(const AutocompleteInput& input) {
|
| - prefetch_data_ = answers_cache_.GetTopAnswerEntry(input.text());
|
| +AnswersQueryData SearchProvider::FindAnswersPrefetchData() {
|
| + // Retrieve the top entry from scored history results.
|
| + MatchMap map;
|
| + AddTransformedHistoryResultsToMap(transformed_keyword_history_results_,
|
| + TemplateURLRef::NO_SUGGESTIONS_AVAILABLE,
|
| + &map);
|
| + AddTransformedHistoryResultsToMap(transformed_default_history_results_,
|
| + TemplateURLRef::NO_SUGGESTIONS_AVAILABLE,
|
| + &map);
|
| +
|
| + ACMatches matches;
|
| + for (MatchMap::const_iterator i(map.begin()); i != map.end(); ++i)
|
| + matches.push_back(i->second);
|
| + std::sort(matches.begin(), matches.end(), &AutocompleteMatch::MoreRelevant);
|
| +
|
| + // If there is a top scoring entry, find the corresponding answer.
|
| + if (!matches.empty())
|
| + return answers_cache_.GetTopAnswerEntry(matches[0].contents);
|
| +
|
| + return AnswersQueryData();
|
| }
|
|
|