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

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: rebase 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 291 matching lines...) Expand 10 before | Expand all | Expand 10 after
302 match.contents_class.push_back( 302 match.contents_class.push_back(
303 ACMatchClassification(input_position, ACMatchClassification::NONE)); 303 ACMatchClassification(input_position, ACMatchClassification::NONE));
304 size_t next_fragment_position = input_position + input_text.length(); 304 size_t next_fragment_position = input_position + input_text.length();
305 if (next_fragment_position < query_string.length()) { 305 if (next_fragment_position < query_string.length()) {
306 match.contents_class.push_back( 306 match.contents_class.push_back(
307 ACMatchClassification(next_fragment_position, 307 ACMatchClassification(next_fragment_position,
308 ACMatchClassification::MATCH)); 308 ACMatchClassification::MATCH));
309 } 309 }
310 } 310 }
311 } else { 311 } else {
312 // Otherwise, we're dealing with the "default search" result which has no 312 // Otherwise, |match| is a verbatim (what-you-typed) match, either for the
313 // completion. 313 // default provider or a keyword search provider.
314 match.contents_class.push_back( 314 match.contents_class.push_back(
315 ACMatchClassification(0, ACMatchClassification::NONE)); 315 ACMatchClassification(0, ACMatchClassification::NONE));
316 match.allowed_to_be_default_match = true;
316 } 317 }
317 318
318 // When the user forced a query, we need to make sure all the fill_into_edit 319 // When the user forced a query, we need to make sure all the fill_into_edit
319 // values preserve that property. Otherwise, if the user starts editing a 320 // values preserve that property. Otherwise, if the user starts editing a
320 // suggestion, non-Search results will suddenly appear. 321 // suggestion, non-Search results will suddenly appear.
321 if (input.type() == AutocompleteInput::FORCED_QUERY) 322 if (input.type() == AutocompleteInput::FORCED_QUERY)
322 match.fill_into_edit.assign(ASCIIToUTF16("?")); 323 match.fill_into_edit.assign(ASCIIToUTF16("?"));
323 if (is_keyword) 324 if (is_keyword)
324 match.fill_into_edit.append(match.keyword + char16(' ')); 325 match.fill_into_edit.append(match.keyword + char16(' '));
325 if (!input.prevent_inline_autocomplete() && 326 if (!input.prevent_inline_autocomplete() &&
326 StartsWith(query_string, input_text, false)) { 327 StartsWith(query_string, input_text, false)) {
327 match.inline_autocompletion = query_string.substr(input_text.length()); 328 match.inline_autocompletion = query_string.substr(input_text.length());
329 match.allowed_to_be_default_match = true;
328 } 330 }
329 match.fill_into_edit.append(query_string); 331 match.fill_into_edit.append(query_string);
330 332
331 const TemplateURLRef& search_url = template_url->url_ref(); 333 const TemplateURLRef& search_url = template_url->url_ref();
332 DCHECK(search_url.SupportsReplacement()); 334 DCHECK(search_url.SupportsReplacement());
333 match.search_terms_args.reset( 335 match.search_terms_args.reset(
334 new TemplateURLRef::SearchTermsArgs(query_string)); 336 new TemplateURLRef::SearchTermsArgs(query_string));
335 match.search_terms_args->original_query = input_text; 337 match.search_terms_args->original_query = input_text;
336 match.search_terms_args->accepted_suggestion = accepted_suggestion; 338 match.search_terms_args->accepted_suggestion = accepted_suggestion;
337 match.search_terms_args->omnibox_start_margin = omnibox_start_margin; 339 match.search_terms_args->omnibox_start_margin = omnibox_start_margin;
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after
503 if (input.text().empty()) { 505 if (input.text().empty()) {
504 // User typed "?" alone. Give them a placeholder result indicating what 506 // User typed "?" alone. Give them a placeholder result indicating what
505 // this syntax does. 507 // this syntax does.
506 if (default_provider) { 508 if (default_provider) {
507 AutocompleteMatch match; 509 AutocompleteMatch match;
508 match.provider = this; 510 match.provider = this;
509 match.contents.assign(l10n_util::GetStringUTF16(IDS_EMPTY_KEYWORD_VALUE)); 511 match.contents.assign(l10n_util::GetStringUTF16(IDS_EMPTY_KEYWORD_VALUE));
510 match.contents_class.push_back( 512 match.contents_class.push_back(
511 ACMatchClassification(0, ACMatchClassification::NONE)); 513 ACMatchClassification(0, ACMatchClassification::NONE));
512 match.keyword = providers_.default_provider(); 514 match.keyword = providers_.default_provider();
515 match.allowed_to_be_default_match = true;
513 matches_.push_back(match); 516 matches_.push_back(match);
514 } 517 }
515 Stop(false); 518 Stop(false);
516 return; 519 return;
517 } 520 }
518 521
519 input_ = input; 522 input_ = input;
520 523
521 DoHistoryQuery(minimal_changes); 524 DoHistoryQuery(minimal_changes);
522 StartOrStopSuggestQuery(minimal_changes); 525 StartOrStopSuggestQuery(minimal_changes);
(...skipping 534 matching lines...) Expand 10 before | Expand all | Expand 10 after
1057 return matches_.front().relevance < 1060 return matches_.front().relevance <
1058 CalculateRelevanceForVerbatimIgnoringKeywordModeState(); 1061 CalculateRelevanceForVerbatimIgnoringKeywordModeState();
1059 } 1062 }
1060 1063
1061 bool SearchProvider::IsTopMatchSearchWithURLInput() const { 1064 bool SearchProvider::IsTopMatchSearchWithURLInput() const {
1062 return input_.type() == AutocompleteInput::URL && 1065 return input_.type() == AutocompleteInput::URL &&
1063 matches_.front().relevance > CalculateRelevanceForVerbatim() && 1066 matches_.front().relevance > CalculateRelevanceForVerbatim() &&
1064 matches_.front().type != AutocompleteMatchType::NAVSUGGEST; 1067 matches_.front().type != AutocompleteMatchType::NAVSUGGEST;
1065 } 1068 }
1066 1069
1067 bool SearchProvider::IsTopMatchNotInlinable() const { 1070 bool SearchProvider::HasValidDefaultMatch(
1068 // Note: this test assumes the SEARCH_OTHER_ENGINE match corresponds to 1071 bool autocomplete_result_will_reorder_for_default_match) const {
1069 // the verbatim search query on the keyword engine. SearchProvider should 1072 // One of the SearchProvider matches may need to be the overall default. If
1070 // not create any other match of type SEARCH_OTHER_ENGINE. 1073 // AutocompleteResult is allowed to reorder matches, this means we simply
1071 return 1074 // need at least one match in the list to be |allowed_to_be_default_match|.
1072 matches_.front().type != AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED && 1075 // If no reordering is possible, however, then our first match needs to have
1073 matches_.front().type != AutocompleteMatchType::SEARCH_OTHER_ENGINE && 1076 // this flag.
1074 matches_.front().inline_autocompletion.empty() && 1077 for (ACMatches::const_iterator it = matches_.begin(); it != matches_.end();
1075 matches_.front().fill_into_edit != input_.text(); 1078 ++it) {
1079 if (it->allowed_to_be_default_match)
1080 return true;
1081 if (!autocomplete_result_will_reorder_for_default_match)
1082 return false;
1083 }
1084 return false;
1076 } 1085 }
1077 1086
1078 void SearchProvider::UpdateMatches() { 1087 void SearchProvider::UpdateMatches() {
1079 ConvertResultsToAutocompleteMatches(); 1088 ConvertResultsToAutocompleteMatches();
1080 1089
1081 // Check constraints that may be violated by suggested relevances. 1090 // Check constraints that may be violated by suggested relevances.
1082 if (!matches_.empty() && 1091 if (!matches_.empty() &&
1083 (default_results_.HasServerProvidedScores() || 1092 (default_results_.HasServerProvidedScores() ||
1084 keyword_results_.HasServerProvidedScores())) { 1093 keyword_results_.HasServerProvidedScores())) {
1085 // These blocks attempt to repair undesirable behavior by suggested 1094 // These blocks attempt to repair undesirable behavior by suggested
1086 // relevances with minimal impact, preserving other suggested relevances. 1095 // relevances with minimal impact, preserving other suggested relevances.
1087 if (IsTopMatchNavigationInKeywordMode()) { 1096 if (IsTopMatchNavigationInKeywordMode()) {
1088 // Correct the suggested relevance scores if the top match is a 1097 // Correct the suggested relevance scores if the top match is a
1089 // navigation in keyword mode, since inlining a navigation match 1098 // navigation in keyword mode, since inlining a navigation match
1090 // would break the user out of keyword mode. By the way, if the top 1099 // would break the user out of keyword mode. By the way, if the top
1091 // match is a non-keyword match (query or navsuggestion) in keyword 1100 // match is a non-keyword match (query or navsuggestion) in keyword
1092 // mode, the user would also break out of keyword mode. However, 1101 // mode, the user would also break out of keyword mode. However,
1093 // that situation is impossible given the current scoring paradigm 1102 // that situation is impossible given the current scoring paradigm
1094 // and the fact that only one search engine (Google) provides suggested 1103 // and the fact that only one search engine (Google) provides suggested
1095 // relevance scores at this time. 1104 // relevance scores at this time.
1096 DemoteKeywordNavigationMatchesPastTopQuery(); 1105 DemoteKeywordNavigationMatchesPastTopQuery();
1097 ConvertResultsToAutocompleteMatches(); 1106 ConvertResultsToAutocompleteMatches();
1098 DCHECK(!IsTopMatchNavigationInKeywordMode()); 1107 DCHECK(!IsTopMatchNavigationInKeywordMode());
1099 } 1108 }
1100 if (IsTopMatchScoreTooLow()) { 1109 // True if the omnibox will reorder matches as necessary to make the top
1110 // one something that is allowed to be the default match.
1111 const bool omnibox_will_reorder_for_legal_default_match =
1112 OmniboxFieldTrial::ReorderForLegalDefaultMatch(
1113 input_.current_page_classification());
1114 if (!omnibox_will_reorder_for_legal_default_match &&
1115 IsTopMatchScoreTooLow()) {
1101 // Disregard the suggested verbatim relevance if the top score is below 1116 // Disregard the suggested verbatim relevance if the top score is below
1102 // the usual verbatim value. For example, a BarProvider may rely on 1117 // the usual verbatim value. For example, a BarProvider may rely on
1103 // SearchProvider's verbatim or inlineable matches for input "foo" to 1118 // SearchProvider's verbatim or inlineable matches for input "foo" (all
1104 // always outrank its own lowly-ranked non-inlineable "bar" match. 1119 // allowed to be default match) to always outrank its own lowly-ranked
1120 // "bar" matches that shouldn't be the default match. This only needs
1121 // to be enforced when the omnibox will not reorder results to make a
1122 // legal default match first.
1105 default_results_.verbatim_relevance = -1; 1123 default_results_.verbatim_relevance = -1;
1106 keyword_results_.verbatim_relevance = -1; 1124 keyword_results_.verbatim_relevance = -1;
1107 ConvertResultsToAutocompleteMatches(); 1125 ConvertResultsToAutocompleteMatches();
1108 } 1126 }
1109 if (IsTopMatchSearchWithURLInput()) { 1127 if (IsTopMatchSearchWithURLInput()) {
1110 // Disregard the suggested search and verbatim relevances if the input 1128 // Disregard the suggested search and verbatim relevances if the input
1111 // type is URL and the top match is a highly-ranked search suggestion. 1129 // type is URL and the top match is a highly-ranked search suggestion.
1112 // For example, prevent a search for "foo.com" from outranking another 1130 // For example, prevent a search for "foo.com" from outranking another
1113 // provider's navigation for "foo.com" or "foo.com/url_from_history". 1131 // provider's navigation for "foo.com" or "foo.com/url_from_history".
1114 ApplyCalculatedSuggestRelevance(&keyword_results_.suggest_results); 1132 ApplyCalculatedSuggestRelevance(&keyword_results_.suggest_results);
1115 ApplyCalculatedSuggestRelevance(&default_results_.suggest_results); 1133 ApplyCalculatedSuggestRelevance(&default_results_.suggest_results);
1116 default_results_.verbatim_relevance = -1; 1134 default_results_.verbatim_relevance = -1;
1117 keyword_results_.verbatim_relevance = -1; 1135 keyword_results_.verbatim_relevance = -1;
1118 ConvertResultsToAutocompleteMatches(); 1136 ConvertResultsToAutocompleteMatches();
1119 } 1137 }
1120 if (IsTopMatchNotInlinable()) { 1138 if (!HasValidDefaultMatch(omnibox_will_reorder_for_legal_default_match)) {
1121 // Disregard suggested relevances if the top match is not a verbatim match 1139 // If the omnibox is not going to reorder results to put a legal default
1122 // or inlinable. For example, input "foo" should not invoke a search for 1140 // match at the top, then this provider needs to guarantee that its top
1123 // "bar", which would happen if the "bar" search match outranked all other 1141 // scoring result is a legal default match (i.e., it's either a verbatim
1124 // matches. 1142 // match or inlinable). For example, input "foo" should not invoke a
1143 // search for "bar", which would happen if the "bar" search match
1144 // outranked all other matches. On the other hand, if the omnibox will
1145 // reorder matches as necessary to put a legal default match at the top,
1146 // all we need to guarantee is that SearchProvider returns a legal
1147 // default match. (The omnibox always needs at least one legal default
1148 // match, and it relies on SearchProvider to always return one.)
1125 ApplyCalculatedRelevance(); 1149 ApplyCalculatedRelevance();
1126 ConvertResultsToAutocompleteMatches(); 1150 ConvertResultsToAutocompleteMatches();
1127 } 1151 }
1128 DCHECK(!IsTopMatchNavigationInKeywordMode()); 1152 DCHECK(!IsTopMatchNavigationInKeywordMode());
1129 DCHECK(!IsTopMatchScoreTooLow()); 1153 DCHECK(omnibox_will_reorder_for_legal_default_match ||
1154 !IsTopMatchScoreTooLow());
1130 DCHECK(!IsTopMatchSearchWithURLInput()); 1155 DCHECK(!IsTopMatchSearchWithURLInput());
1131 DCHECK(!IsTopMatchNotInlinable()); 1156 DCHECK(HasValidDefaultMatch(omnibox_will_reorder_for_legal_default_match));
1132 } 1157 }
1133 1158
1134 UpdateStarredStateOfMatches(); 1159 UpdateStarredStateOfMatches();
1135 UpdateDone(); 1160 UpdateDone();
1136 } 1161 }
1137 1162
1138 void SearchProvider::AddNavigationResultsToMatches( 1163 void SearchProvider::AddNavigationResultsToMatches(
1139 const NavigationResults& navigation_results, 1164 const NavigationResults& navigation_results,
1140 ACMatches* matches) { 1165 ACMatches* matches) {
1141 for (NavigationResults::const_iterator it = navigation_results.begin(); 1166 for (NavigationResults::const_iterator it = navigation_results.begin();
(...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after
1457 const net::FormatUrlTypes format_types = 1482 const net::FormatUrlTypes format_types =
1458 net::kFormatUrlOmitAll & ~(trim_http ? 0 : net::kFormatUrlOmitHTTP); 1483 net::kFormatUrlOmitAll & ~(trim_http ? 0 : net::kFormatUrlOmitHTTP);
1459 match.fill_into_edit += 1484 match.fill_into_edit +=
1460 AutocompleteInput::FormattedStringWithEquivalentMeaning(navigation.url(), 1485 AutocompleteInput::FormattedStringWithEquivalentMeaning(navigation.url(),
1461 net::FormatUrl(navigation.url(), languages, format_types, 1486 net::FormatUrl(navigation.url(), languages, format_types,
1462 net::UnescapeRule::SPACES, NULL, NULL, 1487 net::UnescapeRule::SPACES, NULL, NULL,
1463 &inline_autocomplete_offset)); 1488 &inline_autocomplete_offset));
1464 if (!input_.prevent_inline_autocomplete() && 1489 if (!input_.prevent_inline_autocomplete() &&
1465 (inline_autocomplete_offset != string16::npos)) { 1490 (inline_autocomplete_offset != string16::npos)) {
1466 DCHECK(inline_autocomplete_offset <= match.fill_into_edit.length()); 1491 DCHECK(inline_autocomplete_offset <= match.fill_into_edit.length());
1492 match.allowed_to_be_default_match = true;
1467 match.inline_autocompletion = 1493 match.inline_autocompletion =
1468 match.fill_into_edit.substr(inline_autocomplete_offset); 1494 match.fill_into_edit.substr(inline_autocomplete_offset);
1469 } 1495 }
1470 1496
1471 match.contents = net::FormatUrl(navigation.url(), languages, 1497 match.contents = net::FormatUrl(navigation.url(), languages,
1472 format_types, net::UnescapeRule::SPACES, NULL, NULL, &match_start); 1498 format_types, net::UnescapeRule::SPACES, NULL, NULL, &match_start);
1473 // If the first match in the untrimmed string was inside a scheme that we 1499 // If the first match in the untrimmed string was inside a scheme that we
1474 // trimmed, look for a subsequent match. 1500 // trimmed, look for a subsequent match.
1475 if (match_start == string16::npos) 1501 if (match_start == string16::npos)
1476 match_start = match.contents.find(input); 1502 match_start = match.contents.find(input);
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
1530 it->set_relevance(max_query_relevance); 1556 it->set_relevance(max_query_relevance);
1531 it->set_relevance_from_server(relevance_from_server); 1557 it->set_relevance_from_server(relevance_from_server);
1532 } 1558 }
1533 } 1559 }
1534 1560
1535 void SearchProvider::UpdateDone() { 1561 void SearchProvider::UpdateDone() {
1536 // We're done when the timer isn't running, there are no suggest queries 1562 // We're done when the timer isn't running, there are no suggest queries
1537 // pending, and we're not waiting on Instant. 1563 // pending, and we're not waiting on Instant.
1538 done_ = !timer_.IsRunning() && (suggest_results_pending_ == 0); 1564 done_ = !timer_.IsRunning() && (suggest_results_pending_ == 0);
1539 } 1565 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698