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 "chrome/browser/autocomplete/search_provider.h" | 5 #include "chrome/browser/autocomplete/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 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
239 match.allowed_to_be_default_match = true; | 239 match.allowed_to_be_default_match = true; |
240 matches_.push_back(match); | 240 matches_.push_back(match); |
241 } | 241 } |
242 Stop(true); | 242 Stop(true); |
243 return; | 243 return; |
244 } | 244 } |
245 | 245 |
246 input_ = input; | 246 input_ = input; |
247 | 247 |
248 DoHistoryQuery(minimal_changes); | 248 DoHistoryQuery(minimal_changes); |
249 DoAnswersQuery(input); | 249 // Answers needs the scored history results before any suggest query has been |
Mark P
2014/09/05 22:18:16
nit: omit "the"
groby-ooo-7-16
2014/09/10 23:21:32
Done.
| |
250 // started. | |
Mark P
2014/09/05 22:18:15
Please explain why, either here or elsewhere if th
groby-ooo-7-16
2014/09/10 23:21:37
Done.
| |
251 if (OmniboxFieldTrial::EnableAnswersInSuggest()) { | |
groby-ooo-7-16
2014/08/28 21:36:08
We could _always_ do the scoring after DoHistoryQu
Mark P
2014/09/05 22:18:16
I like your approach in this changelist.
groby-ooo-7-16
2014/09/10 23:21:32
Acknowledged.
| |
252 ScoreHistoryResultsMultiWord( | |
253 default_history_results_, false, &scored_default_history_results_); | |
254 ScoreHistoryResultsMultiWord( | |
255 keyword_history_results_, true, &scored_keyword_history_results_); | |
256 | |
257 prefetch_data_ = FindAnswersPrefetchData(input.text()); | |
258 } | |
Mark P
2014/09/05 22:18:15
Consider:
else { clear all relevant data }
groby-ooo-7-16
2014/09/10 23:21:33
Done.
| |
259 | |
250 StartOrStopSuggestQuery(minimal_changes); | 260 StartOrStopSuggestQuery(minimal_changes); |
251 UpdateMatches(); | 261 UpdateMatches(); |
252 } | 262 } |
253 | 263 |
254 void SearchProvider::Stop(bool clear_cached_results) { | 264 void SearchProvider::Stop(bool clear_cached_results) { |
255 StopSuggest(); | 265 StopSuggest(); |
256 done_ = true; | 266 done_ = true; |
257 | 267 |
258 if (clear_cached_results) | 268 if (clear_cached_results) |
259 ClearAllResults(); | 269 ClearAllResults(); |
(...skipping 614 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
874 } | 884 } |
875 | 885 |
876 void SearchProvider::AddHistoryResultsToMap(const HistoryResults& results, | 886 void SearchProvider::AddHistoryResultsToMap(const HistoryResults& results, |
877 bool is_keyword, | 887 bool is_keyword, |
878 int did_not_accept_suggestion, | 888 int did_not_accept_suggestion, |
879 MatchMap* map) { | 889 MatchMap* map) { |
880 if (results.empty()) | 890 if (results.empty()) |
881 return; | 891 return; |
882 | 892 |
883 base::TimeTicks start_time(base::TimeTicks::Now()); | 893 base::TimeTicks start_time(base::TimeTicks::Now()); |
884 bool prevent_inline_autocomplete = input_.prevent_inline_autocomplete() || | |
885 (input_.type() == metrics::OmniboxInputType::URL); | |
886 const base::string16& input_text = | |
887 is_keyword ? keyword_input_.text() : input_.text(); | |
888 bool input_multiple_words = HasMultipleWords(input_text); | |
889 | 894 |
890 SearchSuggestionParser::SuggestResults scored_results; | 895 // Until Answers becomes default, scoring of history results will still happen |
891 if (!prevent_inline_autocomplete && input_multiple_words) { | 896 // here for non-Answers Chrome, to prevent any impact on timing measurements. |
Mark P
2014/09/05 22:18:16
The reason for this is not "to prevent any impact
groby-ooo-7-16
2014/09/10 23:21:33
Done.
| |
892 // ScoreHistoryResults() allows autocompletion of multi-word, 1-visit | 897 // Answers FieldTrials will instead use scoring results obtained previously. |
Mark P
2014/09/05 22:18:16
nit: "Answers FieldTrials" is awkward. Consider r
groby-ooo-7-16
2014/09/10 23:21:38
Done.
| |
893 // queries if the input also has multiple words. But if we were already | 898 SearchSuggestionParser::SuggestResults local_scored_results; |
894 // scoring a multi-word, multi-visit query aggressively, and the current | 899 const SearchSuggestionParser::SuggestResults* scored_results = NULL; |
895 // input is still a prefix of it, then changing the suggestion suddenly | 900 if (!OmniboxFieldTrial::EnableAnswersInSuggest()) { |
groby-ooo-7-16
2014/08/28 21:36:08
Another repost: Do we want to run unit tests both
Mark P
2014/09/05 22:18:16
It's up to you.
My typical strategy when I add a
groby-ooo-7-16
2014/09/10 23:21:33
They _shouldn't_ behave differently except for Ans
| |
896 // feels wrong. To detect this case, first score as if only one word has | 901 ScoreHistoryResultsMultiWord(results, is_keyword, &local_scored_results); |
897 // been typed, then check if the best result came from aggressive search | 902 scored_results = &local_scored_results; |
898 // history scoring. If it did, then just keep that score set. This | 903 } else { |
899 // 1200 the lowest possible score in CalculateRelevanceForHistory()'s | 904 // TODO(groby): Once answers is on by default, just pass in scored results. |
900 // aggressive-scoring curve. | 905 scored_results = is_keyword ? &scored_keyword_history_results_ |
901 scored_results = ScoreHistoryResults(results, prevent_inline_autocomplete, | 906 : &scored_default_history_results_; |
902 false, input_text, is_keyword); | |
903 if ((scored_results.front().relevance() < 1200) || | |
904 !HasMultipleWords(scored_results.front().suggestion())) | |
905 scored_results.clear(); // Didn't detect the case above, score normally. | |
906 } | 907 } |
907 if (scored_results.empty()) | 908 DCHECK(scored_results); |
908 scored_results = ScoreHistoryResults(results, prevent_inline_autocomplete, | 909 AddScoredHistoryResultsToMap(*scored_results, did_not_accept_suggestion, map); |
909 input_multiple_words, input_text, | |
910 is_keyword); | |
911 for (SearchSuggestionParser::SuggestResults::const_iterator i( | |
912 scored_results.begin()); i != scored_results.end(); ++i) { | |
913 AddMatchToMap(*i, std::string(), did_not_accept_suggestion, true, | |
914 providers_.GetKeywordProviderURL() != NULL, map); | |
915 } | |
916 UMA_HISTOGRAM_TIMES("Omnibox.SearchProvider.AddHistoryResultsTime", | 910 UMA_HISTOGRAM_TIMES("Omnibox.SearchProvider.AddHistoryResultsTime", |
917 base::TimeTicks::Now() - start_time); | 911 base::TimeTicks::Now() - start_time); |
918 } | 912 } |
919 | 913 |
914 // TODO(groby): Can this be merged with AddSuggestResultsToMap? | |
groby-ooo-7-16
2014/08/28 21:36:08
I don't think it can because AddSuggestResults bec
Mark P
2014/09/05 22:18:15
You're reading this wrong. It sets |mark_as_delet
groby-ooo-7-16
2014/09/10 23:21:37
Skipping the merging, then.
| |
915 void SearchProvider::AddScoredHistoryResultsToMap( | |
916 const SearchSuggestionParser::SuggestResults& results, | |
917 int did_not_accept_suggestion, | |
918 MatchMap* map) { | |
919 if (results.empty()) | |
Mark P
2014/09/05 22:18:16
I'm not sure the results.empty() short-circuit is
groby-ooo-7-16
2014/09/10 23:21:37
Done.
| |
920 return; | |
921 | |
922 for (SearchSuggestionParser::SuggestResults::const_iterator i( | |
923 results.begin()); i != results.end(); ++i) { | |
924 AddMatchToMap(*i, std::string(), did_not_accept_suggestion, true, | |
925 providers_.GetKeywordProviderURL() != NULL, map); | |
926 } | |
927 } | |
928 | |
920 SearchSuggestionParser::SuggestResults SearchProvider::ScoreHistoryResults( | 929 SearchSuggestionParser::SuggestResults SearchProvider::ScoreHistoryResults( |
921 const HistoryResults& results, | 930 const HistoryResults& results, |
922 bool base_prevent_inline_autocomplete, | 931 bool base_prevent_inline_autocomplete, |
923 bool input_multiple_words, | 932 bool input_multiple_words, |
924 const base::string16& input_text, | 933 const base::string16& input_text, |
925 bool is_keyword) { | 934 bool is_keyword) { |
926 SearchSuggestionParser::SuggestResults scored_results; | 935 SearchSuggestionParser::SuggestResults scored_results; |
927 // True if the user has asked this exact query previously. | 936 // True if the user has asked this exact query previously. |
928 bool found_what_you_typed_match = false; | 937 bool found_what_you_typed_match = false; |
929 const bool prevent_search_history_inlining = | 938 const bool prevent_search_history_inlining = |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1022 for (SearchSuggestionParser::SuggestResults::iterator i( | 1031 for (SearchSuggestionParser::SuggestResults::iterator i( |
1023 scored_results.begin()); i != scored_results.end(); ++i) { | 1032 scored_results.begin()); i != scored_results.end(); ++i) { |
1024 if ((last_relevance != 0) && (i->relevance() >= last_relevance)) | 1033 if ((last_relevance != 0) && (i->relevance() >= last_relevance)) |
1025 i->set_relevance(last_relevance - 1); | 1034 i->set_relevance(last_relevance - 1); |
1026 last_relevance = i->relevance(); | 1035 last_relevance = i->relevance(); |
1027 } | 1036 } |
1028 | 1037 |
1029 return scored_results; | 1038 return scored_results; |
1030 } | 1039 } |
1031 | 1040 |
1041 void SearchProvider::ScoreHistoryResultsMultiWord( | |
1042 const HistoryResults& results, | |
1043 bool is_keyword, | |
1044 SearchSuggestionParser::SuggestResults* scored_results) { | |
1045 if (results.empty()) | |
Mark P
2014/09/05 22:18:16
Shouldn't we clear scored_results in this case?
groby-ooo-7-16
2014/09/10 23:21:33
Done.
| |
1046 return; | |
1047 | |
1048 bool prevent_inline_autocomplete = | |
1049 input_.prevent_inline_autocomplete() || | |
Mark P
2014/09/05 22:18:16
nit: can't this go on the previous line?
groby-ooo-7-16
2014/09/10 23:21:37
It can. I blame git cl format.
| |
1050 (input_.type() == metrics::OmniboxInputType::URL); | |
1051 const base::string16& input_text = | |
1052 is_keyword ? keyword_input_.text() : input_.text(); | |
Mark P
2014/09/05 22:18:15
Consider GetInput(is_keyword).text()
groby-ooo-7-16
2014/09/10 23:21:38
Done.
| |
1053 bool input_multiple_words = HasMultipleWords(input_text); | |
1054 | |
1055 if (!prevent_inline_autocomplete && input_multiple_words) { | |
1056 // ScoreHistoryResults() allows autocompletion of multi-word, 1-visit | |
1057 // queries if the input also has multiple words. But if we were already | |
1058 // scoring a multi-word, multi-visit query aggressively, and the current | |
1059 // input is still a prefix of it, then changing the suggestion suddenly | |
1060 // feels wrong. To detect this case, first score as if only one word has | |
1061 // been typed, then check if the best result came from aggressive search | |
1062 // history scoring. If it did, then just keep that score set. This | |
1063 // 1200 the lowest possible score in CalculateRelevanceForHistory()'s | |
1064 // aggressive-scoring curve. | |
1065 *scored_results = ScoreHistoryResults( | |
1066 results, prevent_inline_autocomplete, false, input_text, is_keyword); | |
1067 if ((scored_results->front().relevance() < 1200) || | |
1068 !HasMultipleWords(scored_results->front().suggestion())) | |
1069 scored_results->clear(); // Didn't detect the case above, score normally. | |
1070 } | |
1071 if (scored_results->empty()) | |
Mark P
2014/09/05 22:18:15
nit: { }
groby-ooo-7-16
2014/09/10 23:21:33
Done.
| |
1072 *scored_results = ScoreHistoryResults(results, prevent_inline_autocomplete, | |
1073 input_multiple_words, input_text, | |
1074 is_keyword); | |
1075 } | |
1076 | |
1032 void SearchProvider::AddSuggestResultsToMap( | 1077 void SearchProvider::AddSuggestResultsToMap( |
1033 const SearchSuggestionParser::SuggestResults& results, | 1078 const SearchSuggestionParser::SuggestResults& results, |
1034 const std::string& metadata, | 1079 const std::string& metadata, |
1035 MatchMap* map) { | 1080 MatchMap* map) { |
1036 for (size_t i = 0; i < results.size(); ++i) { | 1081 for (size_t i = 0; i < results.size(); ++i) { |
1037 AddMatchToMap(results[i], metadata, i, false, | 1082 AddMatchToMap(results[i], metadata, i, false, |
1038 providers_.GetKeywordProviderURL() != NULL, map); | 1083 providers_.GetKeywordProviderURL() != NULL, map); |
1039 } | 1084 } |
1040 } | 1085 } |
1041 | 1086 |
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1260 if (match->answer_contents.empty() && result.size() > 1) | 1305 if (match->answer_contents.empty() && result.size() > 1) |
1261 ++match; | 1306 ++match; |
1262 if (match->answer_contents.empty() || match->answer_type.empty() || | 1307 if (match->answer_contents.empty() || match->answer_type.empty() || |
1263 match->fill_into_edit.empty()) | 1308 match->fill_into_edit.empty()) |
1264 return; | 1309 return; |
1265 | 1310 |
1266 // Valid answer encountered, cache it for further queries. | 1311 // Valid answer encountered, cache it for further queries. |
1267 answers_cache_.UpdateRecentAnswers(match->fill_into_edit, match->answer_type); | 1312 answers_cache_.UpdateRecentAnswers(match->fill_into_edit, match->answer_type); |
1268 } | 1313 } |
1269 | 1314 |
1270 void SearchProvider::DoAnswersQuery(const AutocompleteInput& input) { | 1315 AnswersQueryData SearchProvider::FindAnswersPrefetchData( |
1271 prefetch_data_ = answers_cache_.GetTopAnswerEntry(input.text()); | 1316 const base::string16& input) { |
1317 // Retrieve the top entry from scored history results. | |
1318 | |
1319 // TODO(groby): This seems a bit of a waste. Figure out if we can either | |
1320 // re-use a partially populated map, or if we should just scan through the | |
1321 // results, duplicates be damned. | |
groby-ooo-7-16
2014/08/28 21:36:08
Re-use of the partial map extends the state the Se
Mark P
2014/09/05 22:18:16
I'm not sure I follow your proposal here.
Note th
groby-ooo-7-16
2014/09/10 23:21:35
We're building the MatchMap twice - once here, onc
Mark P
2014/09/16 22:24:55
Acknowledged.
| |
1322 MatchMap map; | |
1323 // TODO(groby): Can I just default to marking suggestions as "not accepted"? | |
1324 // This seems to only matter for AQS.... | |
groby-ooo-7-16
2014/08/28 21:36:08
See question above.
If I share state, I'll obviou
groby-ooo-7-16
2014/08/28 21:36:08
See question above.
This might also be relevant
Mark P
2014/09/05 22:18:15
No. In fact, the value of did_not_accept_suggesti
Mark P
2014/09/05 22:18:16
ditto: I'm not sure I follow your proposal here.
groby-ooo-7-16
2014/09/10 23:21:33
Shorter: Does it matter that AddTransformed...() i
groby-ooo-7-16
2014/09/10 23:21:33
Acknowledged.
| |
1325 AddScoredHistoryResultsToMap(scored_keyword_history_results_, false, &map); | |
Mark P
2014/09/05 22:18:16
Please do not pass false for an int without an exp
groby-ooo-7-16
2014/09/10 23:21:33
It is indeed - thanks for catching this. I read th
| |
1326 AddScoredHistoryResultsToMap(scored_default_history_results_, false, &map); | |
1327 | |
1328 ACMatches matches; | |
1329 for (MatchMap::const_iterator i(map.begin()); i != map.end(); ++i) | |
1330 matches.push_back(i->second); | |
1331 std::sort(matches.begin(), matches.end(), &AutocompleteMatch::MoreRelevant); | |
1332 | |
1333 // If there is a top scoring entry, find the corresponding answer. | |
1334 if (!matches.empty()) | |
1335 return answers_cache_.GetTopAnswerEntry(matches[0].contents); | |
1336 | |
1337 return AnswersQueryData(); | |
1272 } | 1338 } |
OLD | NEW |