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

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, 5 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 237 matching lines...) Expand 10 before | Expand all | Expand 10 after
248 : AutocompleteProvider(listener, profile, 248 : AutocompleteProvider(listener, profile,
249 AutocompleteProvider::TYPE_SEARCH), 249 AutocompleteProvider::TYPE_SEARCH),
250 providers_(TemplateURLServiceFactory::GetForProfile(profile)), 250 providers_(TemplateURLServiceFactory::GetForProfile(profile)),
251 suggest_results_pending_(0), 251 suggest_results_pending_(0),
252 field_trial_triggered_(false), 252 field_trial_triggered_(false),
253 field_trial_triggered_in_session_(false), 253 field_trial_triggered_in_session_(false),
254 omnibox_start_margin_(-1), 254 omnibox_start_margin_(-1),
255 prevent_search_history_inlining_( 255 prevent_search_history_inlining_(
256 OmniboxFieldTrial::SearchHistoryPreventInlining()), 256 OmniboxFieldTrial::SearchHistoryPreventInlining()),
257 disable_search_history_( 257 disable_search_history_(
258 OmniboxFieldTrial::SearchHistoryDisable()) { 258 OmniboxFieldTrial::SearchHistoryDisable()),
259 omnibox_will_reorder_for_legal_default_match_(
260 OmniboxFieldTrial::InReorderForLegalDefaultMatchGroup()) {
259 } 261 }
260 262
261 // static 263 // static
262 AutocompleteMatch SearchProvider::CreateSearchSuggestion( 264 AutocompleteMatch SearchProvider::CreateSearchSuggestion(
263 AutocompleteProvider* autocomplete_provider, 265 AutocompleteProvider* autocomplete_provider,
264 int relevance, 266 int relevance,
265 AutocompleteMatch::Type type, 267 AutocompleteMatch::Type type,
266 const TemplateURL* template_url, 268 const TemplateURL* template_url,
267 const string16& query_string, 269 const string16& query_string,
268 const string16& input_text, 270 const string16& input_text,
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
304 match.contents_class.push_back( 306 match.contents_class.push_back(
305 ACMatchClassification(input_position, ACMatchClassification::NONE)); 307 ACMatchClassification(input_position, ACMatchClassification::NONE));
306 size_t next_fragment_position = input_position + input_text.length(); 308 size_t next_fragment_position = input_position + input_text.length();
307 if (next_fragment_position < query_string.length()) { 309 if (next_fragment_position < query_string.length()) {
308 match.contents_class.push_back( 310 match.contents_class.push_back(
309 ACMatchClassification(next_fragment_position, 311 ACMatchClassification(next_fragment_position,
310 ACMatchClassification::MATCH)); 312 ACMatchClassification::MATCH));
311 } 313 }
312 } 314 }
313 } else { 315 } else {
314 // Otherwise, we're dealing with the "default search" result which has no 316 // Otherwise, we're dealing with the "default search" result which has no
msw 2013/07/23 21:55:33 nit: please update this comment to something like:
Mark P 2013/07/26 16:48:13 Did something like that with some editing.
315 // completion. 317 // completion.
316 match.contents_class.push_back( 318 match.contents_class.push_back(
317 ACMatchClassification(0, ACMatchClassification::NONE)); 319 ACMatchClassification(0, ACMatchClassification::NONE));
320 match.allowed_to_be_default_match = true;
318 } 321 }
319 322
320 // When the user forced a query, we need to make sure all the fill_into_edit 323 // When the user forced a query, we need to make sure all the fill_into_edit
321 // values preserve that property. Otherwise, if the user starts editing a 324 // values preserve that property. Otherwise, if the user starts editing a
322 // suggestion, non-Search results will suddenly appear. 325 // suggestion, non-Search results will suddenly appear.
323 if (input.type() == AutocompleteInput::FORCED_QUERY) 326 if (input.type() == AutocompleteInput::FORCED_QUERY)
324 match.fill_into_edit.assign(ASCIIToUTF16("?")); 327 match.fill_into_edit.assign(ASCIIToUTF16("?"));
325 if (is_keyword) 328 if (is_keyword)
326 match.fill_into_edit.append(match.keyword + char16(' ')); 329 match.fill_into_edit.append(match.keyword + char16(' '));
327 if (!input.prevent_inline_autocomplete() && 330 if (!input.prevent_inline_autocomplete() &&
328 StartsWith(query_string, input_text, false)) { 331 StartsWith(query_string, input_text, false)) {
329 match.inline_autocompletion = query_string.substr(input_text.length()); 332 match.inline_autocompletion = query_string.substr(input_text.length());
333 match.allowed_to_be_default_match = true;
330 } 334 }
331 match.fill_into_edit.append(query_string); 335 match.fill_into_edit.append(query_string);
332 336
333 const TemplateURLRef& search_url = template_url->url_ref(); 337 const TemplateURLRef& search_url = template_url->url_ref();
334 DCHECK(search_url.SupportsReplacement()); 338 DCHECK(search_url.SupportsReplacement());
335 match.search_terms_args.reset( 339 match.search_terms_args.reset(
336 new TemplateURLRef::SearchTermsArgs(query_string)); 340 new TemplateURLRef::SearchTermsArgs(query_string));
337 match.search_terms_args->original_query = input_text; 341 match.search_terms_args->original_query = input_text;
338 match.search_terms_args->accepted_suggestion = accepted_suggestion; 342 match.search_terms_args->accepted_suggestion = accepted_suggestion;
339 match.search_terms_args->omnibox_start_margin = omnibox_start_margin; 343 match.search_terms_args->omnibox_start_margin = omnibox_start_margin;
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after
509 if (input.text().empty()) { 513 if (input.text().empty()) {
510 // User typed "?" alone. Give them a placeholder result indicating what 514 // User typed "?" alone. Give them a placeholder result indicating what
511 // this syntax does. 515 // this syntax does.
512 if (default_provider) { 516 if (default_provider) {
513 AutocompleteMatch match; 517 AutocompleteMatch match;
514 match.provider = this; 518 match.provider = this;
515 match.contents.assign(l10n_util::GetStringUTF16(IDS_EMPTY_KEYWORD_VALUE)); 519 match.contents.assign(l10n_util::GetStringUTF16(IDS_EMPTY_KEYWORD_VALUE));
516 match.contents_class.push_back( 520 match.contents_class.push_back(
517 ACMatchClassification(0, ACMatchClassification::NONE)); 521 ACMatchClassification(0, ACMatchClassification::NONE));
518 match.keyword = providers_.default_provider(); 522 match.keyword = providers_.default_provider();
523 match.allowed_to_be_default_match = true;
519 matches_.push_back(match); 524 matches_.push_back(match);
520 } 525 }
521 Stop(false); 526 Stop(false);
522 return; 527 return;
523 } 528 }
524 529
525 input_ = input; 530 input_ = input;
526 531
527 DoHistoryQuery(minimal_changes); 532 DoHistoryQuery(minimal_changes);
528 StartOrStopSuggestQuery(minimal_changes); 533 StartOrStopSuggestQuery(minimal_changes);
(...skipping 532 matching lines...) Expand 10 before | Expand all | Expand 10 after
1061 return matches_.front().relevance < 1066 return matches_.front().relevance <
1062 CalculateRelevanceForVerbatimIgnoringKeywordModeState(); 1067 CalculateRelevanceForVerbatimIgnoringKeywordModeState();
1063 } 1068 }
1064 1069
1065 bool SearchProvider::IsTopMatchSearchWithURLInput() const { 1070 bool SearchProvider::IsTopMatchSearchWithURLInput() const {
1066 return input_.type() == AutocompleteInput::URL && 1071 return input_.type() == AutocompleteInput::URL &&
1067 matches_.front().relevance > CalculateRelevanceForVerbatim() && 1072 matches_.front().relevance > CalculateRelevanceForVerbatim() &&
1068 matches_.front().type != AutocompleteMatchType::NAVSUGGEST; 1073 matches_.front().type != AutocompleteMatchType::NAVSUGGEST;
1069 } 1074 }
1070 1075
1071 bool SearchProvider::IsTopMatchNotInlinable() const { 1076 bool SearchProvider::IsTopMatchNotAllowedToBeDefaultMatch() const {
1072 // Note: this test assumes the SEARCH_OTHER_ENGINE match corresponds to 1077 return !matches_.front().allowed_to_be_default_match;
1073 // the verbatim search query on the keyword engine. SearchProvider should 1078 }
1074 // not create any other match of type SEARCH_OTHER_ENGINE. 1079
1075 return 1080 bool SearchProvider::LacksDefaultMatch() const {
1076 matches_.front().type != AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED && 1081 for (ACMatches::const_iterator it = matches_.begin(); it != matches_.end();
1077 matches_.front().type != AutocompleteMatchType::SEARCH_OTHER_ENGINE && 1082 ++it) {
1078 matches_.front().inline_autocompletion.empty() && 1083 if (it->allowed_to_be_default_match)
1079 matches_.front().fill_into_edit != input_.text(); 1084 return false;
1085 }
1086 return true;
1080 } 1087 }
1081 1088
1082 void SearchProvider::UpdateMatches() { 1089 void SearchProvider::UpdateMatches() {
1083 ConvertResultsToAutocompleteMatches(); 1090 ConvertResultsToAutocompleteMatches();
1084 1091
1085 // Check constraints that may be violated by suggested relevances. 1092 // Check constraints that may be violated by suggested relevances.
1086 if (!matches_.empty() && 1093 if (!matches_.empty() &&
1087 (default_results_.HasServerProvidedScores() || 1094 (default_results_.HasServerProvidedScores() ||
1088 keyword_results_.HasServerProvidedScores())) { 1095 keyword_results_.HasServerProvidedScores())) {
1089 // These blocks attempt to repair undesirable behavior by suggested 1096 // These blocks attempt to repair undesirable behavior by suggested
1090 // relevances with minimal impact, preserving other suggested relevances. 1097 // relevances with minimal impact, preserving other suggested relevances.
1091 if (IsTopMatchNavigationInKeywordMode()) { 1098 if (IsTopMatchNavigationInKeywordMode()) {
1092 // Correct the suggested relevance scores if the top match is a 1099 // Correct the suggested relevance scores if the top match is a
1093 // navigation in keyword mode, since inlining a navigation match 1100 // navigation in keyword mode, since inlining a navigation match
1094 // would break the user out of keyword mode. By the way, if the top 1101 // would break the user out of keyword mode. By the way, if the top
1095 // match is a non-keyword match (query or navsuggestion) in keyword 1102 // match is a non-keyword match (query or navsuggestion) in keyword
1096 // mode, the user would also break out of keyword mode. However, 1103 // mode, the user would also break out of keyword mode. However,
1097 // that situation is impossible given the current scoring paradigm 1104 // that situation is impossible given the current scoring paradigm
1098 // and the fact that only one search engine (Google) provides suggested 1105 // and the fact that only one search engine (Google) provides suggested
1099 // relevance scores at this time. 1106 // relevance scores at this time.
1100 DemoteKeywordNavigationMatchesPastTopQuery(); 1107 DemoteKeywordNavigationMatchesPastTopQuery();
1101 ConvertResultsToAutocompleteMatches(); 1108 ConvertResultsToAutocompleteMatches();
1102 DCHECK(!IsTopMatchNavigationInKeywordMode()); 1109 DCHECK(!IsTopMatchNavigationInKeywordMode());
1103 } 1110 }
1104 if (IsTopMatchScoreTooLow()) { 1111 if (!omnibox_will_reorder_for_legal_default_match_ &&
1112 IsTopMatchScoreTooLow()) {
1105 // Disregard the suggested verbatim relevance if the top score is below 1113 // Disregard the suggested verbatim relevance if the top score is below
1106 // the usual verbatim value. For example, a BarProvider may rely on 1114 // the usual verbatim value. For example, a BarProvider may rely on
1107 // SearchProvider's verbatim or inlineable matches for input "foo" to 1115 // SearchProvider's verbatim or inlineable matches for input "foo" (all
1108 // always outrank its own lowly-ranked non-inlineable "bar" match. 1116 // allowed to be default match) to always outrank its own lowly-ranked
1117 // "bar" matches that shouldn't be the default match. This only needs
1118 // to be enforced when the omnibox will not reorder results to make a
1119 // legal default match first.
1109 default_results_.verbatim_relevance = -1; 1120 default_results_.verbatim_relevance = -1;
1110 keyword_results_.verbatim_relevance = -1; 1121 keyword_results_.verbatim_relevance = -1;
1111 ConvertResultsToAutocompleteMatches(); 1122 ConvertResultsToAutocompleteMatches();
1112 } 1123 }
1113 if (IsTopMatchSearchWithURLInput()) { 1124 if (IsTopMatchSearchWithURLInput()) {
1114 // Disregard the suggested search and verbatim relevances if the input 1125 // Disregard the suggested search and verbatim relevances if the input
1115 // type is URL and the top match is a highly-ranked search suggestion. 1126 // type is URL and the top match is a highly-ranked search suggestion.
1116 // For example, prevent a search for "foo.com" from outranking another 1127 // For example, prevent a search for "foo.com" from outranking another
1117 // provider's navigation for "foo.com" or "foo.com/url_from_history". 1128 // provider's navigation for "foo.com" or "foo.com/url_from_history".
1118 ApplyCalculatedSuggestRelevance(&keyword_results_.suggest_results); 1129 ApplyCalculatedSuggestRelevance(&keyword_results_.suggest_results);
1119 ApplyCalculatedSuggestRelevance(&default_results_.suggest_results); 1130 ApplyCalculatedSuggestRelevance(&default_results_.suggest_results);
1120 default_results_.verbatim_relevance = -1; 1131 default_results_.verbatim_relevance = -1;
1121 keyword_results_.verbatim_relevance = -1; 1132 keyword_results_.verbatim_relevance = -1;
1122 ConvertResultsToAutocompleteMatches(); 1133 ConvertResultsToAutocompleteMatches();
1123 } 1134 }
1124 if (IsTopMatchNotInlinable()) { 1135 if (omnibox_will_reorder_for_legal_default_match_ ?
1125 // Disregard suggested relevances if the top match is not a verbatim match 1136 LacksDefaultMatch() : IsTopMatchNotAllowedToBeDefaultMatch()) {
1126 // or inlinable. For example, input "foo" should not invoke a search for 1137 // If the omnibox is not going to reorder results to put a legal default
1127 // "bar", which would happen if the "bar" search match outranked all other 1138 // match at the top, then this provider needs to guarantee that its top
1128 // matches. 1139 // scoring result is a legal default match (i.e., it's either a verbatim
1140 // match or inlinable). For example, input "foo" should not invoke a
1141 // search for "bar", which would happen if the "bar" search match
1142 // outranked all other matches. On the other hand, if the omnibox will
1143 // reorder matches as necessary to put a legal default match at the top,
1144 // all we need to guarantee is that SearchProvider returns a legal
1145 // default match. (The omnibox always needs at least one legal default
1146 // match, and it relies on SearchProvider to always return one.)
1129 ApplyCalculatedRelevance(); 1147 ApplyCalculatedRelevance();
1130 ConvertResultsToAutocompleteMatches(); 1148 ConvertResultsToAutocompleteMatches();
1131 } 1149 }
1132 DCHECK(!IsTopMatchNavigationInKeywordMode()); 1150 DCHECK(!IsTopMatchNavigationInKeywordMode());
1133 DCHECK(!IsTopMatchScoreTooLow()); 1151 DCHECK(omnibox_will_reorder_for_legal_default_match_ ||
1152 !IsTopMatchScoreTooLow());
1134 DCHECK(!IsTopMatchSearchWithURLInput()); 1153 DCHECK(!IsTopMatchSearchWithURLInput());
1135 DCHECK(!IsTopMatchNotInlinable()); 1154 DCHECK(omnibox_will_reorder_for_legal_default_match_ ||
1155 !IsTopMatchNotAllowedToBeDefaultMatch());
1156 DCHECK(!LacksDefaultMatch());
1136 } 1157 }
1137 1158
1138 UpdateStarredStateOfMatches(); 1159 UpdateStarredStateOfMatches();
1139 UpdateDone(); 1160 UpdateDone();
1140 } 1161 }
1141 1162
1142 void SearchProvider::AddNavigationResultsToMatches( 1163 void SearchProvider::AddNavigationResultsToMatches(
1143 const NavigationResults& navigation_results, 1164 const NavigationResults& navigation_results,
1144 ACMatches* matches) { 1165 ACMatches* matches) {
1145 for (NavigationResults::const_iterator it = navigation_results.begin(); 1166 for (NavigationResults::const_iterator it = navigation_results.begin();
(...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after
1441 const net::FormatUrlTypes format_types = 1462 const net::FormatUrlTypes format_types =
1442 net::kFormatUrlOmitAll & ~(trim_http ? 0 : net::kFormatUrlOmitHTTP); 1463 net::kFormatUrlOmitAll & ~(trim_http ? 0 : net::kFormatUrlOmitHTTP);
1443 match.fill_into_edit += 1464 match.fill_into_edit +=
1444 AutocompleteInput::FormattedStringWithEquivalentMeaning(navigation.url(), 1465 AutocompleteInput::FormattedStringWithEquivalentMeaning(navigation.url(),
1445 net::FormatUrl(navigation.url(), languages, format_types, 1466 net::FormatUrl(navigation.url(), languages, format_types,
1446 net::UnescapeRule::SPACES, NULL, NULL, 1467 net::UnescapeRule::SPACES, NULL, NULL,
1447 &inline_autocomplete_offset)); 1468 &inline_autocomplete_offset));
1448 if (!input_.prevent_inline_autocomplete() && 1469 if (!input_.prevent_inline_autocomplete() &&
1449 (inline_autocomplete_offset != string16::npos)) { 1470 (inline_autocomplete_offset != string16::npos)) {
1450 DCHECK(inline_autocomplete_offset <= match.fill_into_edit.length()); 1471 DCHECK(inline_autocomplete_offset <= match.fill_into_edit.length());
1472 match.allowed_to_be_default_match =
1473 (inline_autocomplete_offset != string16::npos);
1451 match.inline_autocompletion = 1474 match.inline_autocompletion =
1452 match.fill_into_edit.substr(inline_autocomplete_offset); 1475 match.fill_into_edit.substr(inline_autocomplete_offset);
1453 } 1476 }
1454 1477
1455 match.contents = net::FormatUrl(navigation.url(), languages, 1478 match.contents = net::FormatUrl(navigation.url(), languages,
1456 format_types, net::UnescapeRule::SPACES, NULL, NULL, &match_start); 1479 format_types, net::UnescapeRule::SPACES, NULL, NULL, &match_start);
1457 // If the first match in the untrimmed string was inside a scheme that we 1480 // If the first match in the untrimmed string was inside a scheme that we
1458 // trimmed, look for a subsequent match. 1481 // trimmed, look for a subsequent match.
1459 if (match_start == string16::npos) 1482 if (match_start == string16::npos)
1460 match_start = match.contents.find(input); 1483 match_start = match.contents.find(input);
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
1514 it->set_relevance(max_query_relevance); 1537 it->set_relevance(max_query_relevance);
1515 it->set_relevance_from_server(relevance_from_server); 1538 it->set_relevance_from_server(relevance_from_server);
1516 } 1539 }
1517 } 1540 }
1518 1541
1519 void SearchProvider::UpdateDone() { 1542 void SearchProvider::UpdateDone() {
1520 // We're done when the timer isn't running, there are no suggest queries 1543 // We're done when the timer isn't running, there are no suggest queries
1521 // pending, and we're not waiting on Instant. 1544 // pending, and we're not waiting on Instant.
1522 done_ = !timer_.IsRunning() && (suggest_results_pending_ == 0); 1545 done_ = !timer_.IsRunning() && (suggest_results_pending_ == 0);
1523 } 1546 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698