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

Side by Side Diff: chrome/browser/autocomplete/search_provider.cc

Issue 18878007: Omnibox: Make the Controller Reorder Matches for Inlining (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Harry's comments Created 7 years, 4 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 | Annotate | Revision Log
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 "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
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698