Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 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 "components/omnibox/search_provider.h" | 5 #include "components/omnibox/search_provider.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <cmath> | 8 #include <cmath> |
| 9 | 9 |
| 10 #include "base/base64.h" | 10 #include "base/base64.h" |
| (...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 258 match.allowed_to_be_default_match = true; | 258 match.allowed_to_be_default_match = true; |
| 259 matches_.push_back(match); | 259 matches_.push_back(match); |
| 260 } | 260 } |
| 261 Stop(true); | 261 Stop(true); |
| 262 return; | 262 return; |
| 263 } | 263 } |
| 264 | 264 |
| 265 input_ = input; | 265 input_ = input; |
| 266 | 266 |
| 267 DoHistoryQuery(minimal_changes); | 267 DoHistoryQuery(minimal_changes); |
| 268 DoAnswersQuery(input); | 268 // Answers needs scored history results before any suggest query has been |
| 269 // started, since the query for answer-bearing results needs additional | |
| 270 // prefetch information based on the highest-scored local history result. | |
| 271 if (OmniboxFieldTrial::EnableAnswersInSuggest()) { | |
| 272 ScoreHistoryResults(raw_default_history_results_, | |
| 273 false, | |
| 274 &transformed_default_history_results_); | |
| 275 ScoreHistoryResults(raw_keyword_history_results_, | |
| 276 true, | |
| 277 &transformed_keyword_history_results_); | |
| 278 | |
|
Mark P
2014/09/25 17:07:26
should we clear the raw_ results here because we d
groby-ooo-7-16
2014/09/25 17:29:32
We could, but a) that requires the fix you describ
| |
| 279 prefetch_data_ = FindAnswersPrefetchData(); | |
| 280 } else { | |
| 281 transformed_default_history_results_.clear(); | |
| 282 transformed_keyword_history_results_.clear(); | |
| 283 } | |
| 284 | |
| 269 StartOrStopSuggestQuery(minimal_changes); | 285 StartOrStopSuggestQuery(minimal_changes); |
| 270 UpdateMatches(); | 286 UpdateMatches(); |
| 271 } | 287 } |
| 272 | 288 |
| 273 void SearchProvider::Stop(bool clear_cached_results) { | 289 void SearchProvider::Stop(bool clear_cached_results) { |
| 274 StopSuggest(); | 290 StopSuggest(); |
| 275 done_ = true; | 291 done_ = true; |
| 276 | 292 |
| 277 if (clear_cached_results) | 293 if (clear_cached_results) |
| 278 ClearAllResults(); | 294 ClearAllResults(); |
| (...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 512 listener_->OnProviderUpdate(false); | 528 listener_->OnProviderUpdate(false); |
| 513 } | 529 } |
| 514 } | 530 } |
| 515 | 531 |
| 516 void SearchProvider::DoHistoryQuery(bool minimal_changes) { | 532 void SearchProvider::DoHistoryQuery(bool minimal_changes) { |
| 517 // The history query results are synchronous, so if minimal_changes is true, | 533 // The history query results are synchronous, so if minimal_changes is true, |
| 518 // we still have the last results and don't need to do anything. | 534 // we still have the last results and don't need to do anything. |
| 519 if (minimal_changes) | 535 if (minimal_changes) |
| 520 return; | 536 return; |
| 521 | 537 |
| 522 keyword_history_results_.clear(); | 538 raw_keyword_history_results_.clear(); |
| 523 default_history_results_.clear(); | 539 raw_default_history_results_.clear(); |
| 524 | 540 |
| 525 if (OmniboxFieldTrial::SearchHistoryDisable( | 541 if (OmniboxFieldTrial::SearchHistoryDisable( |
| 526 input_.current_page_classification())) | 542 input_.current_page_classification())) |
| 527 return; | 543 return; |
| 528 | 544 |
| 529 history::URLDatabase* url_db = client_->InMemoryDatabase(); | 545 history::URLDatabase* url_db = client_->InMemoryDatabase(); |
| 530 if (!url_db) | 546 if (!url_db) |
| 531 return; | 547 return; |
| 532 | 548 |
| 533 // Request history for both the keyword and default provider. We grab many | 549 // Request history for both the keyword and default provider. We grab many |
| 534 // more matches than we'll ultimately clamp to so that if there are several | 550 // more matches than we'll ultimately clamp to so that if there are several |
| 535 // recent multi-word matches who scores are lowered (see | 551 // recent multi-word matches who scores are lowered (see |
| 536 // AddHistoryResultsToMap()), they won't crowd out older, higher-scoring | 552 // ScoreHistoryResults()), they won't crowd out older, higher-scoring |
| 537 // matches. Note that this doesn't fix the problem entirely, but merely | 553 // matches. Note that this doesn't fix the problem entirely, but merely |
| 538 // limits it to cases with a very large number of such multi-word matches; for | 554 // limits it to cases with a very large number of such multi-word matches; for |
| 539 // now, this seems OK compared with the complexity of a real fix, which would | 555 // now, this seems OK compared with the complexity of a real fix, which would |
| 540 // require multiple searches and tracking of "single- vs. multi-word" in the | 556 // require multiple searches and tracking of "single- vs. multi-word" in the |
| 541 // database. | 557 // database. |
| 542 int num_matches = kMaxMatches * 5; | 558 int num_matches = kMaxMatches * 5; |
| 543 const TemplateURL* default_url = providers_.GetDefaultProviderURL(); | 559 const TemplateURL* default_url = providers_.GetDefaultProviderURL(); |
| 544 if (default_url) { | 560 if (default_url) { |
| 545 const base::TimeTicks start_time = base::TimeTicks::Now(); | 561 const base::TimeTicks start_time = base::TimeTicks::Now(); |
| 546 url_db->GetMostRecentKeywordSearchTerms(default_url->id(), input_.text(), | 562 url_db->GetMostRecentKeywordSearchTerms(default_url->id(), |
| 547 num_matches, &default_history_results_); | 563 input_.text(), |
| 564 num_matches, | |
| 565 &raw_default_history_results_); | |
| 548 UMA_HISTOGRAM_TIMES( | 566 UMA_HISTOGRAM_TIMES( |
| 549 "Omnibox.SearchProvider.GetMostRecentKeywordTermsDefaultProviderTime", | 567 "Omnibox.SearchProvider.GetMostRecentKeywordTermsDefaultProviderTime", |
| 550 base::TimeTicks::Now() - start_time); | 568 base::TimeTicks::Now() - start_time); |
| 551 } | 569 } |
| 552 const TemplateURL* keyword_url = providers_.GetKeywordProviderURL(); | 570 const TemplateURL* keyword_url = providers_.GetKeywordProviderURL(); |
| 553 if (keyword_url) { | 571 if (keyword_url) { |
| 554 url_db->GetMostRecentKeywordSearchTerms(keyword_url->id(), | 572 url_db->GetMostRecentKeywordSearchTerms(keyword_url->id(), |
| 555 keyword_input_.text(), num_matches, &keyword_history_results_); | 573 keyword_input_.text(), |
| 574 num_matches, | |
| 575 &raw_keyword_history_results_); | |
| 556 } | 576 } |
| 557 } | 577 } |
| 558 | 578 |
| 559 void SearchProvider::StartOrStopSuggestQuery(bool minimal_changes) { | 579 void SearchProvider::StartOrStopSuggestQuery(bool minimal_changes) { |
| 560 if (!IsQuerySuitableForSuggest()) { | 580 if (!IsQuerySuitableForSuggest()) { |
| 561 StopSuggest(); | 581 StopSuggest(); |
| 562 ClearAllResults(); | 582 ClearAllResults(); |
| 563 return; | 583 return; |
| 564 } | 584 } |
| 565 | 585 |
| (...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 837 trimmed_verbatim, AutocompleteMatchType::SEARCH_OTHER_ENGINE, | 857 trimmed_verbatim, AutocompleteMatchType::SEARCH_OTHER_ENGINE, |
| 838 trimmed_verbatim, base::string16(), base::string16(), | 858 trimmed_verbatim, base::string16(), base::string16(), |
| 839 base::string16(), base::string16(), std::string(), std::string(), | 859 base::string16(), base::string16(), std::string(), std::string(), |
| 840 true, keyword_verbatim_relevance, keyword_relevance_from_server, | 860 true, keyword_verbatim_relevance, keyword_relevance_from_server, |
| 841 false, trimmed_verbatim); | 861 false, trimmed_verbatim); |
| 842 AddMatchToMap(verbatim, std::string(), | 862 AddMatchToMap(verbatim, std::string(), |
| 843 did_not_accept_keyword_suggestion, false, true, &map); | 863 did_not_accept_keyword_suggestion, false, true, &map); |
| 844 } | 864 } |
| 845 } | 865 } |
| 846 } | 866 } |
| 847 AddHistoryResultsToMap(keyword_history_results_, true, | 867 AddRawHistoryResultsToMap(raw_keyword_history_results_, |
| 848 did_not_accept_keyword_suggestion, &map); | 868 true, |
| 849 AddHistoryResultsToMap(default_history_results_, false, | 869 did_not_accept_keyword_suggestion, |
| 850 did_not_accept_default_suggestion, &map); | 870 &map); |
| 871 AddRawHistoryResultsToMap(raw_default_history_results_, | |
| 872 false, | |
| 873 did_not_accept_default_suggestion, | |
| 874 &map); | |
| 851 | 875 |
| 852 AddSuggestResultsToMap(keyword_results_.suggest_results, | 876 AddSuggestResultsToMap(keyword_results_.suggest_results, |
| 853 keyword_results_.metadata, &map); | 877 keyword_results_.metadata, &map); |
| 854 AddSuggestResultsToMap(default_results_.suggest_results, | 878 AddSuggestResultsToMap(default_results_.suggest_results, |
| 855 default_results_.metadata, &map); | 879 default_results_.metadata, &map); |
| 856 | 880 |
| 857 ACMatches matches; | 881 ACMatches matches; |
| 858 for (MatchMap::const_iterator i(map.begin()); i != map.end(); ++i) | 882 for (MatchMap::const_iterator i(map.begin()); i != map.end(); ++i) |
| 859 matches.push_back(i->second); | 883 matches.push_back(i->second); |
| 860 | 884 |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 930 for (SearchSuggestionParser::NavigationResults::const_iterator it = | 954 for (SearchSuggestionParser::NavigationResults::const_iterator it = |
| 931 navigation_results.begin(); it != navigation_results.end(); ++it) { | 955 navigation_results.begin(); it != navigation_results.end(); ++it) { |
| 932 matches->push_back(NavigationToMatch(*it)); | 956 matches->push_back(NavigationToMatch(*it)); |
| 933 // In the absence of suggested relevance scores, use only the single | 957 // In the absence of suggested relevance scores, use only the single |
| 934 // highest-scoring result. (The results are already sorted by relevance.) | 958 // highest-scoring result. (The results are already sorted by relevance.) |
| 935 if (!it->relevance_from_server()) | 959 if (!it->relevance_from_server()) |
| 936 return; | 960 return; |
| 937 } | 961 } |
| 938 } | 962 } |
| 939 | 963 |
| 940 void SearchProvider::AddHistoryResultsToMap(const HistoryResults& results, | 964 void SearchProvider::AddRawHistoryResultsToMap( |
| 941 bool is_keyword, | 965 const HistoryResults& raw_results, |
| 942 int did_not_accept_suggestion, | 966 bool is_keyword, |
|
Mark P
2014/09/25 17:07:27
It's a little awkward that we're passing the resul
groby-ooo-7-16
2014/09/25 17:29:32
We need is_keyword for ScoreHistoryResults in the
| |
| 943 MatchMap* map) { | 967 int did_not_accept_suggestion, |
| 944 if (results.empty()) | 968 MatchMap* map) { |
| 969 if (raw_results.empty()) | |
|
Mark P
2014/09/25 17:01:44
This test for early exit is only appropriate if An
groby-ooo-7-16
2014/09/25 17:29:32
That is correct. (It doesn't matter, though, becau
| |
| 945 return; | 970 return; |
| 946 | 971 |
| 947 base::TimeTicks start_time(base::TimeTicks::Now()); | 972 base::TimeTicks start_time(base::TimeTicks::Now()); |
| 948 bool prevent_inline_autocomplete = input_.prevent_inline_autocomplete() || | |
| 949 (input_.type() == metrics::OmniboxInputType::URL); | |
| 950 const base::string16& input_text = | |
| 951 is_keyword ? keyword_input_.text() : input_.text(); | |
| 952 bool input_multiple_words = HasMultipleWords(input_text); | |
| 953 | 973 |
| 954 SearchSuggestionParser::SuggestResults scored_results; | 974 // Until Answers becomes default, scoring of history results will still happen |
| 955 if (!prevent_inline_autocomplete && input_multiple_words) { | 975 // here for non-Answers Chrome, to prevent scoring performance regressions |
| 956 // ScoreHistoryResults() allows autocompletion of multi-word, 1-visit | 976 // resulting from moving the scoring code before the suggest request is sent. |
| 957 // queries if the input also has multiple words. But if we were already | 977 // For users with Answers enabled, the history results have already been |
| 958 // scoring a multi-word, multi-visit query aggressively, and the current | 978 // scored earlier, right after calling DoHistoryQuery(). |
| 959 // input is still a prefix of it, then changing the suggestion suddenly | 979 SearchSuggestionParser::SuggestResults local_transformed_results; |
| 960 // feels wrong. To detect this case, first score as if only one word has | 980 const SearchSuggestionParser::SuggestResults* transformed_results = NULL; |
| 961 // been typed, then check if the best result came from aggressive search | 981 if (!OmniboxFieldTrial::EnableAnswersInSuggest()) { |
| 962 // history scoring. If it did, then just keep that score set. This | 982 ScoreHistoryResults(raw_results, is_keyword, &local_transformed_results); |
| 963 // 1200 the lowest possible score in CalculateRelevanceForHistory()'s | 983 transformed_results = &local_transformed_results; |
| 964 // aggressive-scoring curve. | 984 } else { |
| 965 scored_results = ScoreHistoryResults(results, prevent_inline_autocomplete, | 985 // TODO(groby): Once answers is on by default, just pass in scored results. |
| 966 false, input_text, is_keyword); | 986 transformed_results = is_keyword ? &transformed_keyword_history_results_ |
| 967 if ((scored_results.front().relevance() < 1200) || | 987 : &transformed_default_history_results_; |
| 968 !HasMultipleWords(scored_results.front().suggestion())) | |
| 969 scored_results.clear(); // Didn't detect the case above, score normally. | |
| 970 } | 988 } |
| 971 if (scored_results.empty()) | 989 DCHECK(transformed_results); |
| 972 scored_results = ScoreHistoryResults(results, prevent_inline_autocomplete, | 990 AddTransformedHistoryResultsToMap( |
| 973 input_multiple_words, input_text, | 991 *transformed_results, did_not_accept_suggestion, map); |
| 974 is_keyword); | |
| 975 for (SearchSuggestionParser::SuggestResults::const_iterator i( | |
| 976 scored_results.begin()); i != scored_results.end(); ++i) { | |
| 977 AddMatchToMap(*i, std::string(), did_not_accept_suggestion, true, | |
| 978 providers_.GetKeywordProviderURL() != NULL, map); | |
| 979 } | |
| 980 UMA_HISTOGRAM_TIMES("Omnibox.SearchProvider.AddHistoryResultsTime", | 992 UMA_HISTOGRAM_TIMES("Omnibox.SearchProvider.AddHistoryResultsTime", |
| 981 base::TimeTicks::Now() - start_time); | 993 base::TimeTicks::Now() - start_time); |
| 982 } | 994 } |
| 983 | 995 |
| 984 SearchSuggestionParser::SuggestResults SearchProvider::ScoreHistoryResults( | 996 void SearchProvider::AddTransformedHistoryResultsToMap( |
| 985 const HistoryResults& results, | 997 const SearchSuggestionParser::SuggestResults& transformed_results, |
| 986 bool base_prevent_inline_autocomplete, | 998 int did_not_accept_suggestion, |
| 987 bool input_multiple_words, | 999 MatchMap* map) { |
| 988 const base::string16& input_text, | 1000 for (SearchSuggestionParser::SuggestResults::const_iterator i( |
| 989 bool is_keyword) { | 1001 transformed_results.begin()); |
| 1002 i != transformed_results.end(); | |
| 1003 ++i) { | |
| 1004 AddMatchToMap(*i, std::string(), did_not_accept_suggestion, true, | |
| 1005 providers_.GetKeywordProviderURL() != NULL, map); | |
| 1006 } | |
| 1007 } | |
| 1008 | |
| 1009 SearchSuggestionParser::SuggestResults | |
| 1010 SearchProvider::ScoreHistoryResultsHelper(const HistoryResults& results, | |
| 1011 bool base_prevent_inline_autocomplete, | |
| 1012 bool input_multiple_words, | |
| 1013 const base::string16& input_text, | |
| 1014 bool is_keyword) { | |
| 990 SearchSuggestionParser::SuggestResults scored_results; | 1015 SearchSuggestionParser::SuggestResults scored_results; |
| 991 // True if the user has asked this exact query previously. | 1016 // True if the user has asked this exact query previously. |
| 992 bool found_what_you_typed_match = false; | 1017 bool found_what_you_typed_match = false; |
| 993 const bool prevent_search_history_inlining = | 1018 const bool prevent_search_history_inlining = |
| 994 OmniboxFieldTrial::SearchHistoryPreventInlining( | 1019 OmniboxFieldTrial::SearchHistoryPreventInlining( |
| 995 input_.current_page_classification()); | 1020 input_.current_page_classification()); |
| 996 const base::string16& trimmed_input = | 1021 const base::string16& trimmed_input = |
| 997 base::CollapseWhitespace(input_text, false); | 1022 base::CollapseWhitespace(input_text, false); |
| 998 for (HistoryResults::const_iterator i(results.begin()); i != results.end(); | 1023 for (HistoryResults::const_iterator i(results.begin()); i != results.end(); |
| 999 ++i) { | 1024 ++i) { |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1085 for (SearchSuggestionParser::SuggestResults::iterator i( | 1110 for (SearchSuggestionParser::SuggestResults::iterator i( |
| 1086 scored_results.begin()); i != scored_results.end(); ++i) { | 1111 scored_results.begin()); i != scored_results.end(); ++i) { |
| 1087 if ((last_relevance != 0) && (i->relevance() >= last_relevance)) | 1112 if ((last_relevance != 0) && (i->relevance() >= last_relevance)) |
| 1088 i->set_relevance(last_relevance - 1); | 1113 i->set_relevance(last_relevance - 1); |
| 1089 last_relevance = i->relevance(); | 1114 last_relevance = i->relevance(); |
| 1090 } | 1115 } |
| 1091 | 1116 |
| 1092 return scored_results; | 1117 return scored_results; |
| 1093 } | 1118 } |
| 1094 | 1119 |
| 1120 void SearchProvider::ScoreHistoryResults( | |
| 1121 const HistoryResults& results, | |
| 1122 bool is_keyword, | |
| 1123 SearchSuggestionParser::SuggestResults* scored_results) { | |
| 1124 DCHECK(scored_results); | |
| 1125 if (results.empty()) { | |
| 1126 scored_results->clear(); | |
| 1127 return; | |
| 1128 } | |
| 1129 | |
| 1130 bool prevent_inline_autocomplete = input_.prevent_inline_autocomplete() || | |
| 1131 (input_.type() == metrics::OmniboxInputType::URL); | |
| 1132 const base::string16& input_text = GetInput(is_keyword).text(); | |
| 1133 bool input_multiple_words = HasMultipleWords(input_text); | |
| 1134 | |
| 1135 if (!prevent_inline_autocomplete && input_multiple_words) { | |
| 1136 // ScoreHistoryResultsHelper() allows autocompletion of multi-word, 1-visit | |
| 1137 // queries if the input also has multiple words. But if we were already | |
| 1138 // scoring a multi-word, multi-visit query aggressively, and the current | |
| 1139 // input is still a prefix of it, then changing the suggestion suddenly | |
| 1140 // feels wrong. To detect this case, first score as if only one word has | |
| 1141 // been typed, then check if the best result came from aggressive search | |
| 1142 // history scoring. If it did, then just keep that score set. This | |
| 1143 // 1200 the lowest possible score in CalculateRelevanceForHistory()'s | |
| 1144 // aggressive-scoring curve. | |
| 1145 *scored_results = ScoreHistoryResultsHelper( | |
| 1146 results, prevent_inline_autocomplete, false, input_text, is_keyword); | |
| 1147 if ((scored_results->front().relevance() < 1200) || | |
| 1148 !HasMultipleWords(scored_results->front().suggestion())) | |
| 1149 scored_results->clear(); // Didn't detect the case above, score normally. | |
| 1150 } | |
| 1151 if (scored_results->empty()) { | |
| 1152 *scored_results = ScoreHistoryResultsHelper(results, | |
| 1153 prevent_inline_autocomplete, | |
| 1154 input_multiple_words, | |
| 1155 input_text, | |
| 1156 is_keyword); | |
| 1157 } | |
| 1158 } | |
| 1159 | |
| 1095 void SearchProvider::AddSuggestResultsToMap( | 1160 void SearchProvider::AddSuggestResultsToMap( |
| 1096 const SearchSuggestionParser::SuggestResults& results, | 1161 const SearchSuggestionParser::SuggestResults& results, |
| 1097 const std::string& metadata, | 1162 const std::string& metadata, |
| 1098 MatchMap* map) { | 1163 MatchMap* map) { |
| 1099 for (size_t i = 0; i < results.size(); ++i) { | 1164 for (size_t i = 0; i < results.size(); ++i) { |
| 1100 AddMatchToMap(results[i], metadata, i, false, | 1165 AddMatchToMap(results[i], metadata, i, false, |
| 1101 providers_.GetKeywordProviderURL() != NULL, map); | 1166 providers_.GetKeywordProviderURL() != NULL, map); |
| 1102 } | 1167 } |
| 1103 } | 1168 } |
| 1104 | 1169 |
| (...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1326 if (match->answer_contents.empty() && result.size() > 1) | 1391 if (match->answer_contents.empty() && result.size() > 1) |
| 1327 ++match; | 1392 ++match; |
| 1328 if (match->answer_contents.empty() || match->answer_type.empty() || | 1393 if (match->answer_contents.empty() || match->answer_type.empty() || |
| 1329 match->fill_into_edit.empty()) | 1394 match->fill_into_edit.empty()) |
| 1330 return; | 1395 return; |
| 1331 | 1396 |
| 1332 // Valid answer encountered, cache it for further queries. | 1397 // Valid answer encountered, cache it for further queries. |
| 1333 answers_cache_.UpdateRecentAnswers(match->fill_into_edit, match->answer_type); | 1398 answers_cache_.UpdateRecentAnswers(match->fill_into_edit, match->answer_type); |
| 1334 } | 1399 } |
| 1335 | 1400 |
| 1336 void SearchProvider::DoAnswersQuery(const AutocompleteInput& input) { | 1401 AnswersQueryData SearchProvider::FindAnswersPrefetchData() { |
| 1337 prefetch_data_ = answers_cache_.GetTopAnswerEntry(input.text()); | 1402 // Retrieve the top entry from scored history results. |
| 1403 MatchMap map; | |
| 1404 AddTransformedHistoryResultsToMap(transformed_keyword_history_results_, | |
| 1405 TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, | |
| 1406 &map); | |
| 1407 AddTransformedHistoryResultsToMap(transformed_default_history_results_, | |
| 1408 TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, | |
| 1409 &map); | |
| 1410 | |
| 1411 ACMatches matches; | |
| 1412 for (MatchMap::const_iterator i(map.begin()); i != map.end(); ++i) | |
| 1413 matches.push_back(i->second); | |
| 1414 std::sort(matches.begin(), matches.end(), &AutocompleteMatch::MoreRelevant); | |
| 1415 | |
| 1416 // If there is a top scoring entry, find the corresponding answer. | |
| 1417 if (!matches.empty()) | |
| 1418 return answers_cache_.GetTopAnswerEntry(matches[0].contents); | |
| 1419 | |
| 1420 return AnswersQueryData(); | |
| 1338 } | 1421 } |
| OLD | NEW |