| 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 768 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 779 } | 779 } |
| 780 | 780 |
| 781 void SearchProvider::ConvertResultsToAutocompleteMatches() { | 781 void SearchProvider::ConvertResultsToAutocompleteMatches() { |
| 782 // Convert all the results to matches and add them to a map, so we can keep | 782 // Convert all the results to matches and add them to a map, so we can keep |
| 783 // the most relevant match for each result. | 783 // the most relevant match for each result. |
| 784 MatchMap map; | 784 MatchMap map; |
| 785 const Time no_time; | 785 const Time no_time; |
| 786 int did_not_accept_keyword_suggestion = keyword_suggest_results_.empty() ? | 786 int did_not_accept_keyword_suggestion = keyword_suggest_results_.empty() ? |
| 787 TemplateURLRef::NO_SUGGESTIONS_AVAILABLE : | 787 TemplateURLRef::NO_SUGGESTIONS_AVAILABLE : |
| 788 TemplateURLRef::NO_SUGGESTION_CHOSEN; | 788 TemplateURLRef::NO_SUGGESTION_CHOSEN; |
| 789 // Keyword what you typed results are handled by the KeywordProvider. | |
| 790 | 789 |
| 791 int verbatim_relevance = GetVerbatimRelevance(); | 790 int verbatim_relevance = GetVerbatimRelevance(); |
| 792 int did_not_accept_default_suggestion = default_suggest_results_.empty() ? | 791 int did_not_accept_default_suggestion = default_suggest_results_.empty() ? |
| 793 TemplateURLRef::NO_SUGGESTIONS_AVAILABLE : | 792 TemplateURLRef::NO_SUGGESTIONS_AVAILABLE : |
| 794 TemplateURLRef::NO_SUGGESTION_CHOSEN; | 793 TemplateURLRef::NO_SUGGESTION_CHOSEN; |
| 795 if (verbatim_relevance > 0) { | 794 if (verbatim_relevance > 0) { |
| 796 AddMatchToMap(input_.text(), input_.text(), verbatim_relevance, | 795 AddMatchToMap(input_.text(), input_.text(), verbatim_relevance, |
| 797 AutocompleteMatch::SEARCH_WHAT_YOU_TYPED, | 796 AutocompleteMatch::SEARCH_WHAT_YOU_TYPED, |
| 798 did_not_accept_default_suggestion, false, &map); | 797 did_not_accept_default_suggestion, false, &map); |
| 799 } | 798 } |
| 800 const size_t what_you_typed_size = map.size(); | 799 if (!keyword_input_.text().empty()) { |
| 800 const TemplateURL* keyword_url = providers_.GetKeywordProviderURL(); |
| 801 // We only create the verbatim search query match for a keyword |
| 802 // if it's not an extension keyword. Extension keywords are handled |
| 803 // in KeywordProvider::Start(). (Extensions are complicated...) |
| 804 // Note: in this provider, SEARCH_OTHER_ENGINE must correspond |
| 805 // to the keyword verbatim search query. Do not create other matches |
| 806 // of type SEARCH_OTHER_ENGINE. |
| 807 if (keyword_url && !keyword_url->IsExtensionKeyword()) { |
| 808 AddMatchToMap(keyword_input_.text(), keyword_input_.text(), |
| 809 CalculateRelevanceForKeywordVerbatim( |
| 810 input_.type(), input_.prefer_keyword()), |
| 811 AutocompleteMatch::SEARCH_OTHER_ENGINE, |
| 812 did_not_accept_keyword_suggestion, true, &map); |
| 813 } |
| 814 } |
| 815 const size_t verbatim_matches_size = map.size(); |
| 801 if (!default_provider_suggestion_.text.empty() && | 816 if (!default_provider_suggestion_.text.empty() && |
| 802 default_provider_suggestion_.type == INSTANT_SUGGESTION_SEARCH && | 817 default_provider_suggestion_.type == INSTANT_SUGGESTION_SEARCH && |
| 803 !input_.prevent_inline_autocomplete()) | 818 !input_.prevent_inline_autocomplete()) |
| 804 AddMatchToMap(input_.text() + default_provider_suggestion_.text, | 819 AddMatchToMap(input_.text() + default_provider_suggestion_.text, |
| 805 input_.text(), verbatim_relevance + 1, | 820 input_.text(), verbatim_relevance + 1, |
| 806 AutocompleteMatch::SEARCH_SUGGEST, | 821 AutocompleteMatch::SEARCH_SUGGEST, |
| 807 did_not_accept_default_suggestion, false, &map); | 822 did_not_accept_default_suggestion, false, &map); |
| 808 | 823 |
| 809 AddHistoryResultsToMap(keyword_history_results_, true, | 824 AddHistoryResultsToMap(keyword_history_results_, true, |
| 810 did_not_accept_keyword_suggestion, &map); | 825 did_not_accept_keyword_suggestion, &map); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 826 // |verbatim_relevance| here. | 841 // |verbatim_relevance| here. |
| 827 matches_.push_back(NavigationToMatch( | 842 matches_.push_back(NavigationToMatch( |
| 828 NavigationResult(GURL(UTF16ToUTF8(default_provider_suggestion_.text)), | 843 NavigationResult(GURL(UTF16ToUTF8(default_provider_suggestion_.text)), |
| 829 string16(), | 844 string16(), |
| 830 kNonURLVerbatimRelevance + 1), | 845 kNonURLVerbatimRelevance + 1), |
| 831 false)); | 846 false)); |
| 832 } | 847 } |
| 833 AddNavigationResultsToMatches(keyword_navigation_results_, true); | 848 AddNavigationResultsToMatches(keyword_navigation_results_, true); |
| 834 AddNavigationResultsToMatches(default_navigation_results_, false); | 849 AddNavigationResultsToMatches(default_navigation_results_, false); |
| 835 | 850 |
| 836 // Allow an additional match for "what you typed" if it's present. | 851 // Allow additional match(es) for verbatim results if present. |
| 837 const size_t max_total_matches = kMaxMatches + what_you_typed_size; | 852 const size_t max_total_matches = kMaxMatches + verbatim_matches_size; |
| 838 std::partial_sort(matches_.begin(), | 853 std::partial_sort(matches_.begin(), |
| 839 matches_.begin() + std::min(max_total_matches, matches_.size()), | 854 matches_.begin() + std::min(max_total_matches, matches_.size()), |
| 840 matches_.end(), &AutocompleteMatch::MoreRelevant); | 855 matches_.end(), &AutocompleteMatch::MoreRelevant); |
| 841 | 856 |
| 842 // If the top match is effectively 'verbatim' but exceeds the calculated | 857 // If the top match is effectively 'verbatim' but exceeds the calculated |
| 843 // verbatim relevance, and REQUESTED_URL |input_| has a |desired_tld| | 858 // verbatim relevance, and REQUESTED_URL |input_| has a |desired_tld| |
| 844 // (for example ".com" when the CTRL key is pressed for REQUESTED_URL input), | 859 // (for example ".com" when the CTRL key is pressed for REQUESTED_URL input), |
| 845 // promote a URL_WHAT_YOU_TYPED match to the top. Otherwise, these matches can | 860 // promote a URL_WHAT_YOU_TYPED match to the top. Otherwise, these matches can |
| 846 // stomp the HistoryURLProvider's similar transient URL_WHAT_YOU_TYPED match, | 861 // stomp the HistoryURLProvider's similar transient URL_WHAT_YOU_TYPED match, |
| 847 // and CTRL+ENTER will invoke the search instead of the expected navigation. | 862 // and CTRL+ENTER will invoke the search instead of the expected navigation. |
| (...skipping 13 matching lines...) Expand all Loading... |
| 861 } | 876 } |
| 862 | 877 |
| 863 bool SearchProvider::IsTopMatchScoreTooLow() const { | 878 bool SearchProvider::IsTopMatchScoreTooLow() const { |
| 864 return matches_.front().relevance < CalculateRelevanceForVerbatim(); | 879 return matches_.front().relevance < CalculateRelevanceForVerbatim(); |
| 865 } | 880 } |
| 866 | 881 |
| 867 bool SearchProvider::IsTopMatchHighRankSearchForURL() const { | 882 bool SearchProvider::IsTopMatchHighRankSearchForURL() const { |
| 868 return input_.type() == AutocompleteInput::URL && | 883 return input_.type() == AutocompleteInput::URL && |
| 869 matches_.front().relevance > CalculateRelevanceForVerbatim() && | 884 matches_.front().relevance > CalculateRelevanceForVerbatim() && |
| 870 (matches_.front().type == AutocompleteMatch::SEARCH_SUGGEST || | 885 (matches_.front().type == AutocompleteMatch::SEARCH_SUGGEST || |
| 871 matches_.front().type == AutocompleteMatch::SEARCH_WHAT_YOU_TYPED); | 886 matches_.front().type == AutocompleteMatch::SEARCH_WHAT_YOU_TYPED || |
| 887 matches_.front().type == AutocompleteMatch::SEARCH_OTHER_ENGINE); |
| 872 } | 888 } |
| 873 | 889 |
| 874 bool SearchProvider::IsTopMatchNotInlinable() const { | 890 bool SearchProvider::IsTopMatchNotInlinable() const { |
| 891 // Note: this test assumes the SEARCH_OTHER_ENGINE match corresponds to |
| 892 // the verbatim search query on the keyword engine. SearchProvider should |
| 893 // not create any other match of type SEARCH_OTHER_ENGINE. |
| 875 return matches_.front().type != AutocompleteMatch::SEARCH_WHAT_YOU_TYPED && | 894 return matches_.front().type != AutocompleteMatch::SEARCH_WHAT_YOU_TYPED && |
| 876 matches_.front().type != AutocompleteMatch::URL_WHAT_YOU_TYPED && | 895 matches_.front().type != AutocompleteMatch::URL_WHAT_YOU_TYPED && |
| 896 matches_.front().type != AutocompleteMatch::SEARCH_OTHER_ENGINE && |
| 877 matches_.front().inline_autocomplete_offset == string16::npos && | 897 matches_.front().inline_autocomplete_offset == string16::npos && |
| 878 matches_.front().fill_into_edit != input_.text(); | 898 matches_.front().fill_into_edit != input_.text(); |
| 879 } | 899 } |
| 880 | 900 |
| 881 void SearchProvider::UpdateMatches() { | 901 void SearchProvider::UpdateMatches() { |
| 882 ConvertResultsToAutocompleteMatches(); | 902 ConvertResultsToAutocompleteMatches(); |
| 883 | 903 |
| 884 // Check constraints that may be violated by suggested relevances. | 904 // Check constraints that may be violated by suggested relevances. |
| 885 if (!matches_.empty() && | 905 if (!matches_.empty() && |
| 886 (has_suggested_relevance_ || verbatim_relevance_ >= 0)) { | 906 (has_suggested_relevance_ || verbatim_relevance_ >= 0)) { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 898 // Disregard the suggested search and verbatim relevances if the input | 918 // Disregard the suggested search and verbatim relevances if the input |
| 899 // type is URL and the top match is a highly-ranked search suggestion. | 919 // type is URL and the top match is a highly-ranked search suggestion. |
| 900 // For example, prevent a search for "foo.com" from outranking another | 920 // For example, prevent a search for "foo.com" from outranking another |
| 901 // provider's navigation for "foo.com" or "foo.com/url_from_history". | 921 // provider's navigation for "foo.com" or "foo.com/url_from_history". |
| 902 ApplyCalculatedSuggestRelevance(&keyword_suggest_results_, true); | 922 ApplyCalculatedSuggestRelevance(&keyword_suggest_results_, true); |
| 903 ApplyCalculatedSuggestRelevance(&default_suggest_results_, false); | 923 ApplyCalculatedSuggestRelevance(&default_suggest_results_, false); |
| 904 verbatim_relevance_ = -1; | 924 verbatim_relevance_ = -1; |
| 905 ConvertResultsToAutocompleteMatches(); | 925 ConvertResultsToAutocompleteMatches(); |
| 906 } | 926 } |
| 907 if (IsTopMatchNotInlinable()) { | 927 if (IsTopMatchNotInlinable()) { |
| 908 // Disregard suggested relevances if the top match is not SWYT, inlinable, | 928 // Disregard suggested relevances if the top match is not a verbatim |
| 909 // or URL_WHAT_YOU_TYPED (which may be top match regardless of inlining). | 929 // match, inlinable, or URL_WHAT_YOU_TYPED (which may be top match |
| 910 // For example, input "foo" should not invoke a search for "bar", which | 930 // regardless of inlining). For example, input "foo" should not |
| 911 // would happen if the "bar" search match outranked all other matches. | 931 // invoke a search for "bar", which would happen if the "bar" search |
| 932 // match outranked all other matches. |
| 912 ApplyCalculatedRelevance(); | 933 ApplyCalculatedRelevance(); |
| 913 ConvertResultsToAutocompleteMatches(); | 934 ConvertResultsToAutocompleteMatches(); |
| 914 } | 935 } |
| 915 DCHECK(!IsTopMatchScoreTooLow()); | 936 DCHECK(!IsTopMatchScoreTooLow()); |
| 916 DCHECK(!IsTopMatchHighRankSearchForURL()); | 937 DCHECK(!IsTopMatchHighRankSearchForURL()); |
| 917 DCHECK(!IsTopMatchNotInlinable()); | 938 DCHECK(!IsTopMatchNotInlinable()); |
| 918 } | 939 } |
| 919 | 940 |
| 920 UpdateStarredStateOfMatches(); | 941 UpdateStarredStateOfMatches(); |
| 921 UpdateDone(); | 942 UpdateDone(); |
| (...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1088 | 1109 |
| 1089 case AutocompleteInput::URL: | 1110 case AutocompleteInput::URL: |
| 1090 return 850; | 1111 return 850; |
| 1091 | 1112 |
| 1092 default: | 1113 default: |
| 1093 NOTREACHED(); | 1114 NOTREACHED(); |
| 1094 return 0; | 1115 return 0; |
| 1095 } | 1116 } |
| 1096 } | 1117 } |
| 1097 | 1118 |
| 1119 // static |
| 1120 int SearchProvider::CalculateRelevanceForKeywordVerbatim( |
| 1121 AutocompleteInput::Type type, |
| 1122 bool prefer_keyword) { |
| 1123 // This function is responsible for scoring verbatim query matches |
| 1124 // for non-extension keywords. KeywordProvider::CalculateRelevance() |
| 1125 // scores verbatim query matches for extension keywords, as well as |
| 1126 // for keyword matches (i.e., suggestions of a keyword itself, not a |
| 1127 // suggestion of a query on a keyword search engine). These two |
| 1128 // functions are currently in sync, but there's no reason we |
| 1129 // couldn't decide in the future to score verbatim matches |
| 1130 // differently for extension and non-extension keywords. If you |
| 1131 // make such a change, however, you should update this comment to |
| 1132 // describe it, so it's clear why the functions diverge. |
| 1133 if (prefer_keyword) |
| 1134 return 1500; |
| 1135 return (type == AutocompleteInput::QUERY) ? 1450 : 1100; |
| 1136 } |
| 1137 |
| 1098 int SearchProvider::CalculateRelevanceForHistory( | 1138 int SearchProvider::CalculateRelevanceForHistory( |
| 1099 const Time& time, | 1139 const Time& time, |
| 1100 bool is_keyword, | 1140 bool is_keyword, |
| 1101 bool prevent_inline_autocomplete) const { | 1141 bool prevent_inline_autocomplete) const { |
| 1102 // The relevance of past searches falls off over time. There are two distinct | 1142 // The relevance of past searches falls off over time. There are two distinct |
| 1103 // equations used. If the first equation is used (searches to the primary | 1143 // equations used. If the first equation is used (searches to the primary |
| 1104 // provider that we want to inline autocomplete), the score starts at 1399 and | 1144 // provider that we want to inline autocomplete), the score starts at 1399 and |
| 1105 // falls to 1300. If the second equation is used the relevance of a search 15 | 1145 // falls to 1300. If the second equation is used the relevance of a search 15 |
| 1106 // minutes ago is discounted 50 points, while the relevance of a search two | 1146 // minutes ago is discounted 50 points, while the relevance of a search two |
| 1107 // weeks ago is discounted 450 points. | 1147 // weeks ago is discounted 450 points. |
| (...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1306 } | 1346 } |
| 1307 | 1347 |
| 1308 void SearchProvider::UpdateDone() { | 1348 void SearchProvider::UpdateDone() { |
| 1309 // We're done when the timer isn't running, there are no suggest queries | 1349 // We're done when the timer isn't running, there are no suggest queries |
| 1310 // pending, and we're not waiting on instant. | 1350 // pending, and we're not waiting on instant. |
| 1311 done_ = (!timer_.IsRunning() && (suggest_results_pending_ == 0) && | 1351 done_ = (!timer_.IsRunning() && (suggest_results_pending_ == 0) && |
| 1312 (instant_finalized_ || | 1352 (instant_finalized_ || |
| 1313 (!chrome::BrowserInstantController::IsInstantEnabled(profile_) && | 1353 (!chrome::BrowserInstantController::IsInstantEnabled(profile_) && |
| 1314 !chrome::search::IsInstantExtendedAPIEnabled(profile_)))); | 1354 !chrome::search::IsInstantExtendedAPIEnabled(profile_)))); |
| 1315 } | 1355 } |
| OLD | NEW |