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 "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/callback.h" | 10 #include "base/callback.h" |
| (...skipping 765 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 776 } | 776 } |
| 777 | 777 |
| 778 void SearchProvider::ConvertResultsToAutocompleteMatches() { | 778 void SearchProvider::ConvertResultsToAutocompleteMatches() { |
| 779 // Convert all the results to matches and add them to a map, so we can keep | 779 // Convert all the results to matches and add them to a map, so we can keep |
| 780 // the most relevant match for each result. | 780 // the most relevant match for each result. |
| 781 MatchMap map; | 781 MatchMap map; |
| 782 const Time no_time; | 782 const Time no_time; |
| 783 int did_not_accept_keyword_suggestion = keyword_suggest_results_.empty() ? | 783 int did_not_accept_keyword_suggestion = keyword_suggest_results_.empty() ? |
| 784 TemplateURLRef::NO_SUGGESTIONS_AVAILABLE : | 784 TemplateURLRef::NO_SUGGESTIONS_AVAILABLE : |
| 785 TemplateURLRef::NO_SUGGESTION_CHOSEN; | 785 TemplateURLRef::NO_SUGGESTION_CHOSEN; |
| 786 // Keyword what you typed results are handled by the KeywordProvider. | |
| 787 | 786 |
| 788 int verbatim_relevance = GetVerbatimRelevance(); | 787 int verbatim_relevance = GetVerbatimRelevance(); |
| 789 int did_not_accept_default_suggestion = default_suggest_results_.empty() ? | 788 int did_not_accept_default_suggestion = default_suggest_results_.empty() ? |
| 790 TemplateURLRef::NO_SUGGESTIONS_AVAILABLE : | 789 TemplateURLRef::NO_SUGGESTIONS_AVAILABLE : |
| 791 TemplateURLRef::NO_SUGGESTION_CHOSEN; | 790 TemplateURLRef::NO_SUGGESTION_CHOSEN; |
| 792 if (verbatim_relevance > 0) { | 791 if (verbatim_relevance > 0) { |
| 793 AddMatchToMap(input_.text(), input_.text(), verbatim_relevance, | 792 AddMatchToMap(input_.text(), input_.text(), verbatim_relevance, |
| 794 AutocompleteMatch::SEARCH_WHAT_YOU_TYPED, | 793 AutocompleteMatch::SEARCH_WHAT_YOU_TYPED, |
| 795 did_not_accept_default_suggestion, false, &map); | 794 did_not_accept_default_suggestion, false, &map); |
| 796 } | 795 } |
| 797 const size_t what_you_typed_size = map.size(); | 796 if (!keyword_input_text_.empty()) { |
| 797 const TemplateURL* keyword_url = providers_.GetKeywordProviderURL(); | |
| 798 // We only create the verbatim search query match for a keyword | |
| 799 // if it's not an extension keyword. Extension keywords are handled | |
| 800 // in KeywordProvider::Start(). (Extensions are complicated...) | |
| 801 // Note: in this provider, SEARCH_OTHER_ENGINE must correspond | |
| 802 // to the keyword verbatim search query. Do not create other matches | |
| 803 // of type SEARCH_OTHER_ENGINE. | |
| 804 if (keyword_url && !keyword_url->IsExtensionKeyword()) { | |
| 805 AddMatchToMap(keyword_input_text_, keyword_input_text_, | |
| 806 CalculateRelevanceForKeywordVerbatim( | |
| 807 input_.type(), input_.prefer_keyword()), | |
| 808 AutocompleteMatch::SEARCH_OTHER_ENGINE, | |
| 809 did_not_accept_keyword_suggestion, true, &map); | |
| 810 } | |
| 811 } | |
| 812 const size_t verbatim_matches_size = map.size(); | |
| 798 if (!default_provider_suggestion_.text.empty() && | 813 if (!default_provider_suggestion_.text.empty() && |
| 799 default_provider_suggestion_.type == INSTANT_SUGGESTION_SEARCH && | 814 default_provider_suggestion_.type == INSTANT_SUGGESTION_SEARCH && |
| 800 !input_.prevent_inline_autocomplete()) | 815 !input_.prevent_inline_autocomplete()) |
| 801 AddMatchToMap(input_.text() + default_provider_suggestion_.text, | 816 AddMatchToMap(input_.text() + default_provider_suggestion_.text, |
| 802 input_.text(), verbatim_relevance + 1, | 817 input_.text(), verbatim_relevance + 1, |
| 803 AutocompleteMatch::SEARCH_SUGGEST, | 818 AutocompleteMatch::SEARCH_SUGGEST, |
| 804 did_not_accept_default_suggestion, false, &map); | 819 did_not_accept_default_suggestion, false, &map); |
| 805 | 820 |
| 806 AddHistoryResultsToMap(keyword_history_results_, true, | 821 AddHistoryResultsToMap(keyword_history_results_, true, |
| 807 did_not_accept_keyword_suggestion, &map); | 822 did_not_accept_keyword_suggestion, &map); |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 823 // |verbatim_relevance| here. | 838 // |verbatim_relevance| here. |
| 824 matches_.push_back(NavigationToMatch( | 839 matches_.push_back(NavigationToMatch( |
| 825 NavigationResult(GURL(UTF16ToUTF8(default_provider_suggestion_.text)), | 840 NavigationResult(GURL(UTF16ToUTF8(default_provider_suggestion_.text)), |
| 826 string16(), | 841 string16(), |
| 827 kNonURLVerbatimRelevance + 1), | 842 kNonURLVerbatimRelevance + 1), |
| 828 false)); | 843 false)); |
| 829 } | 844 } |
| 830 AddNavigationResultsToMatches(keyword_navigation_results_, true); | 845 AddNavigationResultsToMatches(keyword_navigation_results_, true); |
| 831 AddNavigationResultsToMatches(default_navigation_results_, false); | 846 AddNavigationResultsToMatches(default_navigation_results_, false); |
| 832 | 847 |
| 833 // Allow an additional match for "what you typed" if it's present. | 848 // Allow additional match(es) for verbatim results if present. |
| 834 const size_t max_total_matches = kMaxMatches + what_you_typed_size; | 849 const size_t max_total_matches = kMaxMatches + verbatim_matches_size; |
| 835 std::partial_sort(matches_.begin(), | 850 std::partial_sort(matches_.begin(), |
| 836 matches_.begin() + std::min(max_total_matches, matches_.size()), | 851 matches_.begin() + std::min(max_total_matches, matches_.size()), |
| 837 matches_.end(), &AutocompleteMatch::MoreRelevant); | 852 matches_.end(), &AutocompleteMatch::MoreRelevant); |
| 838 | 853 |
| 839 // If the top match is effectively 'verbatim' but exceeds the calculated | 854 // If the top match is effectively 'verbatim' but exceeds the calculated |
| 840 // verbatim relevance, and REQUESTED_URL |input_| has a |desired_tld| | 855 // verbatim relevance, and REQUESTED_URL |input_| has a |desired_tld| |
| 841 // (for example ".com" when the CTRL key is pressed for REQUESTED_URL input), | 856 // (for example ".com" when the CTRL key is pressed for REQUESTED_URL input), |
| 842 // promote a URL_WHAT_YOU_TYPED match to the top. Otherwise, these matches can | 857 // promote a URL_WHAT_YOU_TYPED match to the top. Otherwise, these matches can |
| 843 // stomp the HistoryURLProvider's similar transient URL_WHAT_YOU_TYPED match, | 858 // stomp the HistoryURLProvider's similar transient URL_WHAT_YOU_TYPED match, |
| 844 // and CTRL+ENTER will invoke the search instead of the expected navigation. | 859 // and CTRL+ENTER will invoke the search instead of the expected navigation. |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 858 } | 873 } |
| 859 | 874 |
| 860 bool SearchProvider::IsTopMatchScoreTooLow() const { | 875 bool SearchProvider::IsTopMatchScoreTooLow() const { |
| 861 return matches_.front().relevance < CalculateRelevanceForVerbatim(); | 876 return matches_.front().relevance < CalculateRelevanceForVerbatim(); |
| 862 } | 877 } |
| 863 | 878 |
| 864 bool SearchProvider::IsTopMatchHighRankSearchForURL() const { | 879 bool SearchProvider::IsTopMatchHighRankSearchForURL() const { |
| 865 return input_.type() == AutocompleteInput::URL && | 880 return input_.type() == AutocompleteInput::URL && |
| 866 matches_.front().relevance > CalculateRelevanceForVerbatim() && | 881 matches_.front().relevance > CalculateRelevanceForVerbatim() && |
| 867 (matches_.front().type == AutocompleteMatch::SEARCH_SUGGEST || | 882 (matches_.front().type == AutocompleteMatch::SEARCH_SUGGEST || |
| 868 matches_.front().type == AutocompleteMatch::SEARCH_WHAT_YOU_TYPED); | 883 matches_.front().type == AutocompleteMatch::SEARCH_WHAT_YOU_TYPED || |
| 884 matches_.front().type == AutocompleteMatch::SEARCH_OTHER_ENGINE); | |
| 869 } | 885 } |
| 870 | 886 |
| 871 bool SearchProvider::IsTopMatchNotInlinable() const { | 887 bool SearchProvider::IsTopMatchNotInlinable() const { |
| 888 // Note: this test assumes the SEARCH_OTHER_ENGINE match corresponds to | |
| 889 // the verbatim search query on the keyword engine. SearchProvider should | |
| 890 // not create any other match of type SEARCH_OTHER_ENGINE. We attempt to | |
| 891 // CHECK this assumption in UpdateMatches(). | |
| 872 return matches_.front().type != AutocompleteMatch::SEARCH_WHAT_YOU_TYPED && | 892 return matches_.front().type != AutocompleteMatch::SEARCH_WHAT_YOU_TYPED && |
| 873 matches_.front().type != AutocompleteMatch::URL_WHAT_YOU_TYPED && | 893 matches_.front().type != AutocompleteMatch::URL_WHAT_YOU_TYPED && |
| 894 matches_.front().type != AutocompleteMatch::SEARCH_OTHER_ENGINE && | |
| 874 matches_.front().inline_autocomplete_offset == string16::npos && | 895 matches_.front().inline_autocomplete_offset == string16::npos && |
| 875 matches_.front().fill_into_edit != input_.text(); | 896 matches_.front().fill_into_edit != input_.text(); |
| 876 } | 897 } |
| 877 | 898 |
| 878 void SearchProvider::UpdateMatches() { | 899 void SearchProvider::UpdateMatches() { |
| 879 ConvertResultsToAutocompleteMatches(); | 900 ConvertResultsToAutocompleteMatches(); |
| 880 | 901 |
| 902 #ifdef DEBUG | |
|
msw
2013/02/05 01:35:19
Shoot, I thought you were going to put this into a
Mark P
2013/02/05 19:50:55
Removed.
At least it's now in the code review his
| |
| 903 // Check that SEARCH_OTHER_ENGINE match is actually the verbatim search | |
| 904 // query on the keyword provider. | |
| 905 for (int i = 0; i < matches_.size(); ++i) { | |
| 906 const AutocompleteMatch& m = matches_[i]; | |
| 907 if (m.type == AutocompleteMatch::SEARCH_OTHER_ENGINE) { | |
| 908 // Verify that input_.text() begins with the keyword (possibly | |
| 909 // with an ignorable prefix before it) and ends with the text | |
| 910 // displayed in this match and that the only text in between is | |
| 911 // entirely whitespace. | |
| 912 const URLPrefix* prefix = | |
| 913 URLPrefix::BestURLPrefix(input_.text(), ""); | |
| 914 // There will always be a valid prefix; it may be empty. | |
| 915 DCHECK(prefix); | |
| 916 string16 input_after_prefix = input_.text().substr(prefix.length()); | |
| 917 // case-insensitive for keyword name | |
| 918 DCHECK(base::StartsWith(input_after_prefix, m.keyword, false)); | |
| 919 string16 input_after_keyword = | |
| 920 input_after_prefix.substr(m.keyword.length()); | |
| 921 // case-sensitive match for remaining text | |
| 922 DCHECK(base::EndsWith(input_after_keyword, m.contents, true)); | |
| 923 string16::size_t pos_of_remaining_text = | |
| 924 input_after_keyword.find(m.contents); | |
| 925 DCHECK_NE(pos_of_remaining_text, string16::npos); | |
| 926 DCHECK_GT(pos_of_remaining_text, 0u); | |
| 927 DCHECK(base::ContainsOnlyWhitespace( | |
| 928 input_after_keyword.substr(0, pos_of_remaining_text))); | |
| 929 } | |
| 930 } | |
| 931 #endif | |
| 932 | |
| 881 // Check constraints that may be violated by suggested relevances. | 933 // Check constraints that may be violated by suggested relevances. |
| 882 if (!matches_.empty() && | 934 if (!matches_.empty() && |
| 883 (has_suggested_relevance_ || verbatim_relevance_ >= 0)) { | 935 (has_suggested_relevance_ || verbatim_relevance_ >= 0)) { |
| 884 // These two blocks attempt to repair undesriable behavior by suggested | 936 // These two blocks attempt to repair undesriable behavior by suggested |
| 885 // relevances with minimal impact, preserving other suggested relevances. | 937 // relevances with minimal impact, preserving other suggested relevances. |
| 886 if (IsTopMatchScoreTooLow()) { | 938 if (IsTopMatchScoreTooLow()) { |
| 887 // Disregard the suggested verbatim relevance if the top score is below | 939 // Disregard the suggested verbatim relevance if the top score is below |
| 888 // the usual verbatim value. For example, a BarProvider may rely on | 940 // the usual verbatim value. For example, a BarProvider may rely on |
| 889 // SearchProvider's verbatim or inlineable matches for input "foo" to | 941 // SearchProvider's verbatim or inlineable matches for input "foo" to |
| 890 // always outrank its own lowly-ranked non-inlineable "bar" match. | 942 // always outrank its own lowly-ranked non-inlineable "bar" match. |
| 891 verbatim_relevance_ = -1; | 943 verbatim_relevance_ = -1; |
| 892 ConvertResultsToAutocompleteMatches(); | 944 ConvertResultsToAutocompleteMatches(); |
| 893 } | 945 } |
| 894 if (IsTopMatchHighRankSearchForURL()) { | 946 if (IsTopMatchHighRankSearchForURL()) { |
| 895 // Disregard the suggested search and verbatim relevances if the input | 947 // Disregard the suggested search and verbatim relevances if the input |
| 896 // type is URL and the top match is a highly-ranked search suggestion. | 948 // type is URL and the top match is a highly-ranked search suggestion. |
| 897 // For example, prevent a search for "foo.com" from outranking another | 949 // For example, prevent a search for "foo.com" from outranking another |
| 898 // provider's navigation for "foo.com" or "foo.com/url_from_history". | 950 // provider's navigation for "foo.com" or "foo.com/url_from_history". |
| 899 ApplyCalculatedSuggestRelevance(&keyword_suggest_results_, true); | 951 ApplyCalculatedSuggestRelevance(&keyword_suggest_results_, true); |
| 900 ApplyCalculatedSuggestRelevance(&default_suggest_results_, false); | 952 ApplyCalculatedSuggestRelevance(&default_suggest_results_, false); |
| 901 verbatim_relevance_ = -1; | 953 verbatim_relevance_ = -1; |
| 902 ConvertResultsToAutocompleteMatches(); | 954 ConvertResultsToAutocompleteMatches(); |
| 903 } | 955 } |
| 904 if (IsTopMatchNotInlinable()) { | 956 if (IsTopMatchNotInlinable()) { |
| 905 // Disregard suggested relevances if the top match is not SWYT, inlinable, | 957 // Disregard suggested relevances if the top match is not a verbatim |
| 906 // or URL_WHAT_YOU_TYPED (which may be top match regardless of inlining). | 958 // match, inlinable, or URL_WHAT_YOU_TYPED (which may be top match |
| 907 // For example, input "foo" should not invoke a search for "bar", which | 959 // regardless of inlining). For example, input "foo" should not |
| 908 // would happen if the "bar" search match outranked all other matches. | 960 // invoke a search for "bar", which would happen if the "bar" search |
| 961 // match outranked all other matches. | |
| 909 ApplyCalculatedRelevance(); | 962 ApplyCalculatedRelevance(); |
| 910 ConvertResultsToAutocompleteMatches(); | 963 ConvertResultsToAutocompleteMatches(); |
| 911 } | 964 } |
| 912 DCHECK(!IsTopMatchScoreTooLow()); | 965 DCHECK(!IsTopMatchScoreTooLow()); |
| 913 DCHECK(!IsTopMatchHighRankSearchForURL()); | 966 DCHECK(!IsTopMatchHighRankSearchForURL()); |
| 914 DCHECK(!IsTopMatchNotInlinable()); | 967 DCHECK(!IsTopMatchNotInlinable()); |
| 915 } | 968 } |
| 916 | 969 |
| 917 UpdateStarredStateOfMatches(); | 970 UpdateStarredStateOfMatches(); |
| 918 UpdateDone(); | 971 UpdateDone(); |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1083 | 1136 |
| 1084 case AutocompleteInput::URL: | 1137 case AutocompleteInput::URL: |
| 1085 return 850; | 1138 return 850; |
| 1086 | 1139 |
| 1087 default: | 1140 default: |
| 1088 NOTREACHED(); | 1141 NOTREACHED(); |
| 1089 return 0; | 1142 return 0; |
| 1090 } | 1143 } |
| 1091 } | 1144 } |
| 1092 | 1145 |
| 1146 // static | |
| 1147 int SearchProvider::CalculateRelevanceForKeywordVerbatim( | |
| 1148 AutocompleteInput::Type type, | |
| 1149 bool prefer_keyword) { | |
| 1150 // Perhaps this should be kept similar to | |
| 1151 // KeywordProvider::CalculateRelevance(). That function calculates, | |
| 1152 // among other things, the verbatim query score for search keywords | |
| 1153 // but only extension-based ones. It would be a bit odd if the score | |
| 1154 // for a verbatim query for an extension keyword and for a | |
| 1155 // non-extension keyword differed dramatically (though no immediate | |
| 1156 // harm would come from it). | |
| 1157 if (prefer_keyword) | |
| 1158 return 1500; | |
| 1159 return type == AutocompleteInput::QUERY ? 1450 : 1100; | |
| 1160 } | |
| 1161 | |
| 1093 int SearchProvider::CalculateRelevanceForHistory( | 1162 int SearchProvider::CalculateRelevanceForHistory( |
| 1094 const Time& time, | 1163 const Time& time, |
| 1095 bool is_keyword, | 1164 bool is_keyword, |
| 1096 bool prevent_inline_autocomplete) const { | 1165 bool prevent_inline_autocomplete) const { |
| 1097 // The relevance of past searches falls off over time. There are two distinct | 1166 // The relevance of past searches falls off over time. There are two distinct |
| 1098 // equations used. If the first equation is used (searches to the primary | 1167 // equations used. If the first equation is used (searches to the primary |
| 1099 // provider that we want to inline autocomplete), the score starts at 1399 and | 1168 // provider that we want to inline autocomplete), the score starts at 1399 and |
| 1100 // falls to 1300. If the second equation is used the relevance of a search 15 | 1169 // falls to 1300. If the second equation is used the relevance of a search 15 |
| 1101 // minutes ago is discounted 50 points, while the relevance of a search two | 1170 // minutes ago is discounted 50 points, while the relevance of a search two |
| 1102 // weeks ago is discounted 450 points. | 1171 // weeks ago is discounted 450 points. |
| (...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1301 } | 1370 } |
| 1302 | 1371 |
| 1303 void SearchProvider::UpdateDone() { | 1372 void SearchProvider::UpdateDone() { |
| 1304 // We're done when the timer isn't running, there are no suggest queries | 1373 // We're done when the timer isn't running, there are no suggest queries |
| 1305 // pending, and we're not waiting on instant. | 1374 // pending, and we're not waiting on instant. |
| 1306 done_ = (!timer_.IsRunning() && (suggest_results_pending_ == 0) && | 1375 done_ = (!timer_.IsRunning() && (suggest_results_pending_ == 0) && |
| 1307 (instant_finalized_ || | 1376 (instant_finalized_ || |
| 1308 (!chrome::BrowserInstantController::IsInstantEnabled(profile_) && | 1377 (!chrome::BrowserInstantController::IsInstantEnabled(profile_) && |
| 1309 !chrome::search::IsInstantExtendedAPIEnabled(profile_)))); | 1378 !chrome::search::IsInstantExtendedAPIEnabled(profile_)))); |
| 1310 } | 1379 } |
| OLD | NEW |