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 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
300 match.contents_class.push_back( | 300 match.contents_class.push_back( |
301 ACMatchClassification(input_position, ACMatchClassification::NONE)); | 301 ACMatchClassification(input_position, ACMatchClassification::NONE)); |
302 size_t next_fragment_position = input_position + input_text.length(); | 302 size_t next_fragment_position = input_position + input_text.length(); |
303 if (next_fragment_position < query_string.length()) { | 303 if (next_fragment_position < query_string.length()) { |
304 match.contents_class.push_back( | 304 match.contents_class.push_back( |
305 ACMatchClassification(next_fragment_position, | 305 ACMatchClassification(next_fragment_position, |
306 ACMatchClassification::MATCH)); | 306 ACMatchClassification::MATCH)); |
307 } | 307 } |
308 } | 308 } |
309 } else { | 309 } else { |
310 // Otherwise, we're dealing with the "default search" result which has no | 310 // Otherwise, |match| is a verbatim (what-you-typed) match, either for the |
311 // completion. | 311 // default provider or a keyword search provider. |
312 match.contents_class.push_back( | 312 match.contents_class.push_back( |
313 ACMatchClassification(0, ACMatchClassification::NONE)); | 313 ACMatchClassification(0, ACMatchClassification::NONE)); |
314 match.allowed_to_be_default_match = true; | |
314 } | 315 } |
315 | 316 |
316 // When the user forced a query, we need to make sure all the fill_into_edit | 317 // When the user forced a query, we need to make sure all the fill_into_edit |
317 // values preserve that property. Otherwise, if the user starts editing a | 318 // values preserve that property. Otherwise, if the user starts editing a |
318 // suggestion, non-Search results will suddenly appear. | 319 // suggestion, non-Search results will suddenly appear. |
319 if (input.type() == AutocompleteInput::FORCED_QUERY) | 320 if (input.type() == AutocompleteInput::FORCED_QUERY) |
320 match.fill_into_edit.assign(ASCIIToUTF16("?")); | 321 match.fill_into_edit.assign(ASCIIToUTF16("?")); |
321 if (is_keyword) | 322 if (is_keyword) |
322 match.fill_into_edit.append(match.keyword + char16(' ')); | 323 match.fill_into_edit.append(match.keyword + char16(' ')); |
323 if (!input.prevent_inline_autocomplete() && | 324 if (!input.prevent_inline_autocomplete() && |
324 StartsWith(query_string, input_text, false)) { | 325 StartsWith(query_string, input_text, false)) { |
325 match.inline_autocompletion = query_string.substr(input_text.length()); | 326 match.inline_autocompletion = query_string.substr(input_text.length()); |
327 match.allowed_to_be_default_match = true; | |
326 } | 328 } |
327 match.fill_into_edit.append(query_string); | 329 match.fill_into_edit.append(query_string); |
328 | 330 |
329 const TemplateURLRef& search_url = template_url->url_ref(); | 331 const TemplateURLRef& search_url = template_url->url_ref(); |
330 DCHECK(search_url.SupportsReplacement()); | 332 DCHECK(search_url.SupportsReplacement()); |
331 match.search_terms_args.reset( | 333 match.search_terms_args.reset( |
332 new TemplateURLRef::SearchTermsArgs(query_string)); | 334 new TemplateURLRef::SearchTermsArgs(query_string)); |
333 match.search_terms_args->original_query = input_text; | 335 match.search_terms_args->original_query = input_text; |
334 match.search_terms_args->accepted_suggestion = accepted_suggestion; | 336 match.search_terms_args->accepted_suggestion = accepted_suggestion; |
335 match.search_terms_args->omnibox_start_margin = omnibox_start_margin; | 337 match.search_terms_args->omnibox_start_margin = omnibox_start_margin; |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
505 if (input.text().empty()) { | 507 if (input.text().empty()) { |
506 // User typed "?" alone. Give them a placeholder result indicating what | 508 // User typed "?" alone. Give them a placeholder result indicating what |
507 // this syntax does. | 509 // this syntax does. |
508 if (default_provider) { | 510 if (default_provider) { |
509 AutocompleteMatch match; | 511 AutocompleteMatch match; |
510 match.provider = this; | 512 match.provider = this; |
511 match.contents.assign(l10n_util::GetStringUTF16(IDS_EMPTY_KEYWORD_VALUE)); | 513 match.contents.assign(l10n_util::GetStringUTF16(IDS_EMPTY_KEYWORD_VALUE)); |
512 match.contents_class.push_back( | 514 match.contents_class.push_back( |
513 ACMatchClassification(0, ACMatchClassification::NONE)); | 515 ACMatchClassification(0, ACMatchClassification::NONE)); |
514 match.keyword = providers_.default_provider(); | 516 match.keyword = providers_.default_provider(); |
517 match.allowed_to_be_default_match = true; | |
515 matches_.push_back(match); | 518 matches_.push_back(match); |
516 } | 519 } |
517 Stop(false); | 520 Stop(false); |
518 return; | 521 return; |
519 } | 522 } |
520 | 523 |
521 input_ = input; | 524 input_ = input; |
522 | 525 |
523 DoHistoryQuery(minimal_changes); | 526 DoHistoryQuery(minimal_changes); |
524 StartOrStopSuggestQuery(minimal_changes); | 527 StartOrStopSuggestQuery(minimal_changes); |
(...skipping 533 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1058 return matches_.front().relevance < | 1061 return matches_.front().relevance < |
1059 CalculateRelevanceForVerbatimIgnoringKeywordModeState(); | 1062 CalculateRelevanceForVerbatimIgnoringKeywordModeState(); |
1060 } | 1063 } |
1061 | 1064 |
1062 bool SearchProvider::IsTopMatchSearchWithURLInput() const { | 1065 bool SearchProvider::IsTopMatchSearchWithURLInput() const { |
1063 return input_.type() == AutocompleteInput::URL && | 1066 return input_.type() == AutocompleteInput::URL && |
1064 matches_.front().relevance > CalculateRelevanceForVerbatim() && | 1067 matches_.front().relevance > CalculateRelevanceForVerbatim() && |
1065 matches_.front().type != AutocompleteMatchType::NAVSUGGEST; | 1068 matches_.front().type != AutocompleteMatchType::NAVSUGGEST; |
1066 } | 1069 } |
1067 | 1070 |
1068 bool SearchProvider::IsTopMatchNotInlinable() const { | 1071 bool SearchProvider::LacksValidDefaultMatch( |
Peter Kasting
2013/08/06 22:56:16
Nit: I think this function's body would read more
Mark P
2013/08/07 00:44:31
I chose Lacks...() for consistency with the other
Peter Kasting
2013/08/07 00:49:53
I don't see any particular benefit to being consis
Mark P
2013/08/07 00:58:52
Done.
| |
1069 // Note: this test assumes the SEARCH_OTHER_ENGINE match corresponds to | 1072 bool omnibox_will_reorder_for_legal_default_match) const { |
1070 // the verbatim search query on the keyword engine. SearchProvider should | 1073 // If the omnibox will reorder matches to put something allowed to be the |
1071 // not create any other match of type SEARCH_OTHER_ENGINE. | 1074 // default match first, then lacking a valid default match means there is |
1072 return | 1075 // no match allowed to be default. If the omnibox will not reorder matches, |
1073 matches_.front().type != AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED && | 1076 // then lacking a valid default match means the top match is not allowed |
1074 matches_.front().type != AutocompleteMatchType::SEARCH_OTHER_ENGINE && | 1077 // to be the default match. |
Peter Kasting
2013/08/06 22:56:16
Nit: This comment is somewhat confusing. How abou
Mark P
2013/08/07 00:44:31
Yes, that is clearer. Used that comment.
| |
1075 matches_.front().inline_autocompletion.empty() && | 1078 for (ACMatches::const_iterator it = matches_.begin(); it != matches_.end(); |
1076 matches_.front().fill_into_edit != input_.text(); | 1079 ++it) { |
1080 if (it->allowed_to_be_default_match) | |
1081 return false; | |
1082 if (!omnibox_will_reorder_for_legal_default_match) | |
1083 return true; | |
1084 } | |
1085 return true; | |
1077 } | 1086 } |
1078 | 1087 |
1079 void SearchProvider::UpdateMatches() { | 1088 void SearchProvider::UpdateMatches() { |
1080 ConvertResultsToAutocompleteMatches(); | 1089 ConvertResultsToAutocompleteMatches(); |
1081 | 1090 |
1082 // Check constraints that may be violated by suggested relevances. | 1091 // Check constraints that may be violated by suggested relevances. |
1083 if (!matches_.empty() && | 1092 if (!matches_.empty() && |
1084 (default_results_.HasServerProvidedScores() || | 1093 (default_results_.HasServerProvidedScores() || |
1085 keyword_results_.HasServerProvidedScores())) { | 1094 keyword_results_.HasServerProvidedScores())) { |
1086 // These blocks attempt to repair undesirable behavior by suggested | 1095 // These blocks attempt to repair undesirable behavior by suggested |
1087 // relevances with minimal impact, preserving other suggested relevances. | 1096 // relevances with minimal impact, preserving other suggested relevances. |
1088 if (IsTopMatchNavigationInKeywordMode()) { | 1097 if (IsTopMatchNavigationInKeywordMode()) { |
1089 // Correct the suggested relevance scores if the top match is a | 1098 // Correct the suggested relevance scores if the top match is a |
1090 // navigation in keyword mode, since inlining a navigation match | 1099 // navigation in keyword mode, since inlining a navigation match |
1091 // would break the user out of keyword mode. By the way, if the top | 1100 // would break the user out of keyword mode. By the way, if the top |
1092 // match is a non-keyword match (query or navsuggestion) in keyword | 1101 // match is a non-keyword match (query or navsuggestion) in keyword |
1093 // mode, the user would also break out of keyword mode. However, | 1102 // mode, the user would also break out of keyword mode. However, |
1094 // that situation is impossible given the current scoring paradigm | 1103 // that situation is impossible given the current scoring paradigm |
1095 // and the fact that only one search engine (Google) provides suggested | 1104 // and the fact that only one search engine (Google) provides suggested |
1096 // relevance scores at this time. | 1105 // relevance scores at this time. |
1097 DemoteKeywordNavigationMatchesPastTopQuery(); | 1106 DemoteKeywordNavigationMatchesPastTopQuery(); |
1098 ConvertResultsToAutocompleteMatches(); | 1107 ConvertResultsToAutocompleteMatches(); |
1099 DCHECK(!IsTopMatchNavigationInKeywordMode()); | 1108 DCHECK(!IsTopMatchNavigationInKeywordMode()); |
1100 } | 1109 } |
1101 if (IsTopMatchScoreTooLow()) { | 1110 // True if the omnibox will reorder matches as necessary to make the top |
1111 // one something that is allowed to be the default match. | |
1112 const bool omnibox_will_reorder_for_legal_default_match = | |
1113 OmniboxFieldTrial::ReorderForLegalDefaultMatch( | |
1114 input_.current_page_classification()); | |
1115 if (!omnibox_will_reorder_for_legal_default_match && | |
1116 IsTopMatchScoreTooLow()) { | |
1102 // Disregard the suggested verbatim relevance if the top score is below | 1117 // Disregard the suggested verbatim relevance if the top score is below |
1103 // the usual verbatim value. For example, a BarProvider may rely on | 1118 // the usual verbatim value. For example, a BarProvider may rely on |
1104 // SearchProvider's verbatim or inlineable matches for input "foo" to | 1119 // SearchProvider's verbatim or inlineable matches for input "foo" (all |
1105 // always outrank its own lowly-ranked non-inlineable "bar" match. | 1120 // allowed to be default match) to always outrank its own lowly-ranked |
1121 // "bar" matches that shouldn't be the default match. This only needs | |
1122 // to be enforced when the omnibox will not reorder results to make a | |
1123 // legal default match first. | |
1106 default_results_.verbatim_relevance = -1; | 1124 default_results_.verbatim_relevance = -1; |
1107 keyword_results_.verbatim_relevance = -1; | 1125 keyword_results_.verbatim_relevance = -1; |
1108 ConvertResultsToAutocompleteMatches(); | 1126 ConvertResultsToAutocompleteMatches(); |
1109 } | 1127 } |
1110 if (IsTopMatchSearchWithURLInput()) { | 1128 if (IsTopMatchSearchWithURLInput()) { |
1111 // Disregard the suggested search and verbatim relevances if the input | 1129 // Disregard the suggested search and verbatim relevances if the input |
1112 // type is URL and the top match is a highly-ranked search suggestion. | 1130 // type is URL and the top match is a highly-ranked search suggestion. |
1113 // For example, prevent a search for "foo.com" from outranking another | 1131 // For example, prevent a search for "foo.com" from outranking another |
1114 // provider's navigation for "foo.com" or "foo.com/url_from_history". | 1132 // provider's navigation for "foo.com" or "foo.com/url_from_history". |
1115 ApplyCalculatedSuggestRelevance(&keyword_results_.suggest_results); | 1133 ApplyCalculatedSuggestRelevance(&keyword_results_.suggest_results); |
1116 ApplyCalculatedSuggestRelevance(&default_results_.suggest_results); | 1134 ApplyCalculatedSuggestRelevance(&default_results_.suggest_results); |
1117 default_results_.verbatim_relevance = -1; | 1135 default_results_.verbatim_relevance = -1; |
1118 keyword_results_.verbatim_relevance = -1; | 1136 keyword_results_.verbatim_relevance = -1; |
1119 ConvertResultsToAutocompleteMatches(); | 1137 ConvertResultsToAutocompleteMatches(); |
1120 } | 1138 } |
1121 if (IsTopMatchNotInlinable()) { | 1139 if (LacksValidDefaultMatch(omnibox_will_reorder_for_legal_default_match)) { |
1122 // Disregard suggested relevances if the top match is not a verbatim match | 1140 // If the omnibox is not going to reorder results to put a legal default |
1123 // or inlinable. For example, input "foo" should not invoke a search for | 1141 // match at the top, then this provider needs to guarantee that its top |
1124 // "bar", which would happen if the "bar" search match outranked all other | 1142 // scoring result is a legal default match (i.e., it's either a verbatim |
1125 // matches. | 1143 // match or inlinable). For example, input "foo" should not invoke a |
1144 // search for "bar", which would happen if the "bar" search match | |
1145 // outranked all other matches. On the other hand, if the omnibox will | |
1146 // reorder matches as necessary to put a legal default match at the top, | |
1147 // all we need to guarantee is that SearchProvider returns a legal | |
1148 // default match. (The omnibox always needs at least one legal default | |
1149 // match, and it relies on SearchProvider to always return one.) | |
Peter Kasting
2013/08/06 22:56:16
Nit: Given the comments in LacksValidDefaultMatch(
Mark P
2013/08/07 00:44:31
I know it's mostly redundant but I think it's usef
| |
1126 ApplyCalculatedRelevance(); | 1150 ApplyCalculatedRelevance(); |
1127 ConvertResultsToAutocompleteMatches(); | 1151 ConvertResultsToAutocompleteMatches(); |
1128 } | 1152 } |
1129 DCHECK(!IsTopMatchNavigationInKeywordMode()); | 1153 DCHECK(!IsTopMatchNavigationInKeywordMode()); |
1130 DCHECK(!IsTopMatchScoreTooLow()); | 1154 DCHECK(omnibox_will_reorder_for_legal_default_match || |
1155 !IsTopMatchScoreTooLow()); | |
Peter Kasting
2013/08/06 22:56:16
Nit: Indent 4, not even
Mark P
2013/08/07 00:44:31
Done.
| |
1131 DCHECK(!IsTopMatchSearchWithURLInput()); | 1156 DCHECK(!IsTopMatchSearchWithURLInput()); |
1132 DCHECK(!IsTopMatchNotInlinable()); | 1157 DCHECK(!LacksValidDefaultMatch( |
1158 omnibox_will_reorder_for_legal_default_match)); | |
1133 } | 1159 } |
1134 | 1160 |
1135 UpdateStarredStateOfMatches(); | 1161 UpdateStarredStateOfMatches(); |
1136 UpdateDone(); | 1162 UpdateDone(); |
1137 } | 1163 } |
1138 | 1164 |
1139 void SearchProvider::AddNavigationResultsToMatches( | 1165 void SearchProvider::AddNavigationResultsToMatches( |
1140 const NavigationResults& navigation_results, | 1166 const NavigationResults& navigation_results, |
1141 ACMatches* matches) { | 1167 ACMatches* matches) { |
1142 for (NavigationResults::const_iterator it = navigation_results.begin(); | 1168 for (NavigationResults::const_iterator it = navigation_results.begin(); |
(...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1443 const net::FormatUrlTypes format_types = | 1469 const net::FormatUrlTypes format_types = |
1444 net::kFormatUrlOmitAll & ~(trim_http ? 0 : net::kFormatUrlOmitHTTP); | 1470 net::kFormatUrlOmitAll & ~(trim_http ? 0 : net::kFormatUrlOmitHTTP); |
1445 match.fill_into_edit += | 1471 match.fill_into_edit += |
1446 AutocompleteInput::FormattedStringWithEquivalentMeaning(navigation.url(), | 1472 AutocompleteInput::FormattedStringWithEquivalentMeaning(navigation.url(), |
1447 net::FormatUrl(navigation.url(), languages, format_types, | 1473 net::FormatUrl(navigation.url(), languages, format_types, |
1448 net::UnescapeRule::SPACES, NULL, NULL, | 1474 net::UnescapeRule::SPACES, NULL, NULL, |
1449 &inline_autocomplete_offset)); | 1475 &inline_autocomplete_offset)); |
1450 if (!input_.prevent_inline_autocomplete() && | 1476 if (!input_.prevent_inline_autocomplete() && |
1451 (inline_autocomplete_offset != string16::npos)) { | 1477 (inline_autocomplete_offset != string16::npos)) { |
1452 DCHECK(inline_autocomplete_offset <= match.fill_into_edit.length()); | 1478 DCHECK(inline_autocomplete_offset <= match.fill_into_edit.length()); |
1479 match.allowed_to_be_default_match = | |
1480 (inline_autocomplete_offset != string16::npos); | |
Peter Kasting
2013/08/06 22:56:16
Eh? The conditional above has already guaranteed
Mark P
2013/08/07 00:44:31
Replaced with "true" :-).
| |
1453 match.inline_autocompletion = | 1481 match.inline_autocompletion = |
1454 match.fill_into_edit.substr(inline_autocomplete_offset); | 1482 match.fill_into_edit.substr(inline_autocomplete_offset); |
1455 } | 1483 } |
1456 | 1484 |
1457 match.contents = net::FormatUrl(navigation.url(), languages, | 1485 match.contents = net::FormatUrl(navigation.url(), languages, |
1458 format_types, net::UnescapeRule::SPACES, NULL, NULL, &match_start); | 1486 format_types, net::UnescapeRule::SPACES, NULL, NULL, &match_start); |
1459 // If the first match in the untrimmed string was inside a scheme that we | 1487 // If the first match in the untrimmed string was inside a scheme that we |
1460 // trimmed, look for a subsequent match. | 1488 // trimmed, look for a subsequent match. |
1461 if (match_start == string16::npos) | 1489 if (match_start == string16::npos) |
1462 match_start = match.contents.find(input); | 1490 match_start = match.contents.find(input); |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1516 it->set_relevance(max_query_relevance); | 1544 it->set_relevance(max_query_relevance); |
1517 it->set_relevance_from_server(relevance_from_server); | 1545 it->set_relevance_from_server(relevance_from_server); |
1518 } | 1546 } |
1519 } | 1547 } |
1520 | 1548 |
1521 void SearchProvider::UpdateDone() { | 1549 void SearchProvider::UpdateDone() { |
1522 // We're done when the timer isn't running, there are no suggest queries | 1550 // We're done when the timer isn't running, there are no suggest queries |
1523 // pending, and we're not waiting on Instant. | 1551 // pending, and we're not waiting on Instant. |
1524 done_ = !timer_.IsRunning() && (suggest_results_pending_ == 0); | 1552 done_ = !timer_.IsRunning() && (suggest_results_pending_ == 0); |
1525 } | 1553 } |
OLD | NEW |