Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(526)

Side by Side Diff: components/omnibox/search_provider.cc

Issue 470313004: [AiS] Use top local result for prefetch. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Review fixes. Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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 ScoreHistoryResultsMultiWord(raw_default_history_results_,
273 false,
274 &transformed_default_history_results_);
275 ScoreHistoryResultsMultiWord(raw_keyword_history_results_,
276 true,
277 &transformed_keyword_history_results_);
278
279 prefetch_data_ = FindAnswersPrefetchData(input.text());
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
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 // ScoreHistoryResultsMultiWord()), 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
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
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,
943 MatchMap* map) { 967 int did_not_accept_suggestion,
944 if (results.empty()) 968 MatchMap* map) {
969 if (raw_results.empty())
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 regressions from moving the
Mark P 2014/09/16 22:24:55 nit: ^scoring^performance (I think) If you are wo
groby-ooo-7-16 2014/09/18 23:27:24 performance regressions, indeed.
956 // ScoreHistoryResults() allows autocompletion of multi-word, 1-visit 976 // 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 ScoreHistoryResultsMultiWord(
963 // 1200 the lowest possible score in CalculateRelevanceForHistory()'s 983 raw_results, is_keyword, &local_transformed_results);
964 // aggressive-scoring curve. 984 transformed_results = &local_transformed_results;
965 scored_results = ScoreHistoryResults(results, prevent_inline_autocomplete, 985 } else {
966 false, input_text, is_keyword); 986 // TODO(groby): Once answers is on by default, just pass in scored results.
967 if ((scored_results.front().relevance() < 1200) || 987 transformed_results = is_keyword ? &transformed_keyword_history_results_
Mark P 2014/09/16 22:24:55 I'd prefer if you could add somewhere (possibly he
groby-ooo-7-16 2014/09/18 23:27:24 I'm not sure I understand why results would be ann
Mark P 2014/09/19 18:45:36 Thank you for the explanation. I see my worry was
968 !HasMultipleWords(scored_results.front().suggestion())) 988 : &transformed_default_history_results_;
969 scored_results.clear(); // Didn't detect the case above, score normally.
970 } 989 }
971 if (scored_results.empty()) 990 DCHECK(transformed_results);
972 scored_results = ScoreHistoryResults(results, prevent_inline_autocomplete, 991 AddTransformedHistoryResultsToMap(
973 input_multiple_words, input_text, 992 *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", 993 UMA_HISTOGRAM_TIMES("Omnibox.SearchProvider.AddHistoryResultsTime",
981 base::TimeTicks::Now() - start_time); 994 base::TimeTicks::Now() - start_time);
982 } 995 }
983 996
997 void SearchProvider::AddTransformedHistoryResultsToMap(
998 const SearchSuggestionParser::SuggestResults& transformed_results,
999 int did_not_accept_suggestion,
1000 MatchMap* map) {
1001 for (SearchSuggestionParser::SuggestResults::const_iterator i(
1002 transformed_results.begin());
1003 i != transformed_results.end();
1004 ++i) {
1005 AddMatchToMap(*i, std::string(), did_not_accept_suggestion, true,
1006 providers_.GetKeywordProviderURL() != NULL, map);
1007 }
1008 }
1009
984 SearchSuggestionParser::SuggestResults SearchProvider::ScoreHistoryResults( 1010 SearchSuggestionParser::SuggestResults SearchProvider::ScoreHistoryResults(
985 const HistoryResults& results, 1011 const HistoryResults& results,
986 bool base_prevent_inline_autocomplete, 1012 bool base_prevent_inline_autocomplete,
987 bool input_multiple_words, 1013 bool input_multiple_words,
988 const base::string16& input_text, 1014 const base::string16& input_text,
989 bool is_keyword) { 1015 bool is_keyword) {
990 SearchSuggestionParser::SuggestResults scored_results; 1016 SearchSuggestionParser::SuggestResults scored_results;
991 // True if the user has asked this exact query previously. 1017 // True if the user has asked this exact query previously.
992 bool found_what_you_typed_match = false; 1018 bool found_what_you_typed_match = false;
993 const bool prevent_search_history_inlining = 1019 const bool prevent_search_history_inlining =
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
1085 for (SearchSuggestionParser::SuggestResults::iterator i( 1111 for (SearchSuggestionParser::SuggestResults::iterator i(
1086 scored_results.begin()); i != scored_results.end(); ++i) { 1112 scored_results.begin()); i != scored_results.end(); ++i) {
1087 if ((last_relevance != 0) && (i->relevance() >= last_relevance)) 1113 if ((last_relevance != 0) && (i->relevance() >= last_relevance))
1088 i->set_relevance(last_relevance - 1); 1114 i->set_relevance(last_relevance - 1);
1089 last_relevance = i->relevance(); 1115 last_relevance = i->relevance();
1090 } 1116 }
1091 1117
1092 return scored_results; 1118 return scored_results;
1093 } 1119 }
1094 1120
1121 void SearchProvider::ScoreHistoryResultsMultiWord(
1122 const HistoryResults& results,
1123 bool is_keyword,
1124 SearchSuggestionParser::SuggestResults* scored_results) {
1125 DCHECK(scored_results);
1126 if (results.empty()) {
1127 scored_results->clear();
1128 return;
1129 }
1130
1131 bool prevent_inline_autocomplete = input_.prevent_inline_autocomplete() ||
1132 (input_.type() == metrics::OmniboxInputType::URL);
1133 const base::string16& input_text = GetInput(is_keyword).text();
1134 bool input_multiple_words = HasMultipleWords(input_text);
1135
1136 if (!prevent_inline_autocomplete && input_multiple_words) {
1137 // ScoreHistoryResults() allows autocompletion of multi-word, 1-visit
1138 // queries if the input also has multiple words. But if we were already
1139 // scoring a multi-word, multi-visit query aggressively, and the current
1140 // input is still a prefix of it, then changing the suggestion suddenly
1141 // feels wrong. To detect this case, first score as if only one word has
1142 // been typed, then check if the best result came from aggressive search
1143 // history scoring. If it did, then just keep that score set. This
1144 // 1200 the lowest possible score in CalculateRelevanceForHistory()'s
1145 // aggressive-scoring curve.
1146 *scored_results = ScoreHistoryResults(
1147 results, prevent_inline_autocomplete, false, input_text, is_keyword);
1148 if ((scored_results->front().relevance() < 1200) ||
1149 !HasMultipleWords(scored_results->front().suggestion()))
1150 scored_results->clear(); // Didn't detect the case above, score normally.
1151 }
1152 if (scored_results->empty()) {
1153 *scored_results = ScoreHistoryResults(results,
1154 prevent_inline_autocomplete,
1155 input_multiple_words,
1156 input_text,
1157 is_keyword);
1158 }
1159 }
1160
1095 void SearchProvider::AddSuggestResultsToMap( 1161 void SearchProvider::AddSuggestResultsToMap(
1096 const SearchSuggestionParser::SuggestResults& results, 1162 const SearchSuggestionParser::SuggestResults& results,
1097 const std::string& metadata, 1163 const std::string& metadata,
1098 MatchMap* map) { 1164 MatchMap* map) {
1099 for (size_t i = 0; i < results.size(); ++i) { 1165 for (size_t i = 0; i < results.size(); ++i) {
1100 AddMatchToMap(results[i], metadata, i, false, 1166 AddMatchToMap(results[i], metadata, i, false,
1101 providers_.GetKeywordProviderURL() != NULL, map); 1167 providers_.GetKeywordProviderURL() != NULL, map);
1102 } 1168 }
1103 } 1169 }
1104 1170
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after
1326 if (match->answer_contents.empty() && result.size() > 1) 1392 if (match->answer_contents.empty() && result.size() > 1)
1327 ++match; 1393 ++match;
1328 if (match->answer_contents.empty() || match->answer_type.empty() || 1394 if (match->answer_contents.empty() || match->answer_type.empty() ||
1329 match->fill_into_edit.empty()) 1395 match->fill_into_edit.empty())
1330 return; 1396 return;
1331 1397
1332 // Valid answer encountered, cache it for further queries. 1398 // Valid answer encountered, cache it for further queries.
1333 answers_cache_.UpdateRecentAnswers(match->fill_into_edit, match->answer_type); 1399 answers_cache_.UpdateRecentAnswers(match->fill_into_edit, match->answer_type);
1334 } 1400 }
1335 1401
1336 void SearchProvider::DoAnswersQuery(const AutocompleteInput& input) { 1402 AnswersQueryData SearchProvider::FindAnswersPrefetchData(
1337 prefetch_data_ = answers_cache_.GetTopAnswerEntry(input.text()); 1403 const base::string16& input) {
1404 // Retrieve the top entry from scored history results.
1405
1406 // TODO(groby): This seems a bit of a waste. Figure out if we can either
1407 // re-use a partially populated map, or if we should just scan through the
1408 // results, duplicates be damned.
Mark P 2014/09/16 22:24:55 Given that you've discarded this idea (fine by me)
groby-ooo-7-16 2014/09/18 23:27:24 Done.
1409 MatchMap map;
1410 // TODO(groby): Can I just default to marking suggestions as "not accepted"?
1411 // This seems to only matter for AQS....
Mark P 2014/09/16 22:24:55 I'm comfortable with this here. As I understand i
groby-ooo-7-16 2014/09/18 23:27:24 Correct, so removed comment.
1412 AddTransformedHistoryResultsToMap(transformed_keyword_history_results_,
1413 TemplateURLRef::NO_SUGGESTIONS_AVAILABLE,
1414 &map);
1415 AddTransformedHistoryResultsToMap(transformed_default_history_results_,
1416 TemplateURLRef::NO_SUGGESTIONS_AVAILABLE,
1417 &map);
1418
1419 ACMatches matches;
1420 for (MatchMap::const_iterator i(map.begin()); i != map.end(); ++i)
1421 matches.push_back(i->second);
1422 std::sort(matches.begin(), matches.end(), &AutocompleteMatch::MoreRelevant);
1423
1424 LOG(ERROR) << "SIZE:" << matches.size();
Mark P 2014/09/16 22:24:55 nit: remove unneeded LOG lines
groby-ooo-7-16 2014/09/18 23:27:24 Done.
1425
1426 // If there is a top scoring entry, find the corresponding answer.
1427 if (!matches.empty() &&
1428 StartsWith(matches[0].contents, input, false /* case-insensitive */)) {
Mark P 2014/09/16 22:24:55 Minor question: why this is StartsWith necessary?
groby-ooo-7-16 2014/09/18 23:27:24 By missing you mean leaving the test out completel
Mark P 2014/09/19 18:45:36 Yes, search history matches should always be prefi
1429 return answers_cache_.GetTopAnswerEntry(matches[0].contents);
1430 }
1431 return AnswersQueryData();
1338 } 1432 }
OLDNEW
« components/omnibox/search_provider.h ('K') | « components/omnibox/search_provider.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698