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

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: Peter's comments 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 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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_autocomplete_offset = 332 match.inline_autocomplete_offset =
330 match.fill_into_edit.length() + input_text.length(); 333 match.fill_into_edit.length() + input_text.length();
334 match.allowed_to_be_default_match = true;
331 } 335 }
332 match.fill_into_edit.append(query_string); 336 match.fill_into_edit.append(query_string);
333 337
334 const TemplateURLRef& search_url = template_url->url_ref(); 338 const TemplateURLRef& search_url = template_url->url_ref();
335 DCHECK(search_url.SupportsReplacement()); 339 DCHECK(search_url.SupportsReplacement());
336 match.search_terms_args.reset( 340 match.search_terms_args.reset(
337 new TemplateURLRef::SearchTermsArgs(query_string)); 341 new TemplateURLRef::SearchTermsArgs(query_string));
338 match.search_terms_args->original_query = input_text; 342 match.search_terms_args->original_query = input_text;
339 match.search_terms_args->accepted_suggestion = accepted_suggestion; 343 match.search_terms_args->accepted_suggestion = accepted_suggestion;
340 match.search_terms_args->omnibox_start_margin = omnibox_start_margin; 344 match.search_terms_args->omnibox_start_margin = omnibox_start_margin;
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after
510 if (input.text().empty()) { 514 if (input.text().empty()) {
511 // User typed "?" alone. Give them a placeholder result indicating what 515 // User typed "?" alone. Give them a placeholder result indicating what
512 // this syntax does. 516 // this syntax does.
513 if (default_provider) { 517 if (default_provider) {
514 AutocompleteMatch match; 518 AutocompleteMatch match;
515 match.provider = this; 519 match.provider = this;
516 match.contents.assign(l10n_util::GetStringUTF16(IDS_EMPTY_KEYWORD_VALUE)); 520 match.contents.assign(l10n_util::GetStringUTF16(IDS_EMPTY_KEYWORD_VALUE));
517 match.contents_class.push_back( 521 match.contents_class.push_back(
518 ACMatchClassification(0, ACMatchClassification::NONE)); 522 ACMatchClassification(0, ACMatchClassification::NONE));
519 match.keyword = providers_.default_provider(); 523 match.keyword = providers_.default_provider();
524 match.allowed_to_be_default_match = true;
520 matches_.push_back(match); 525 matches_.push_back(match);
521 } 526 }
522 Stop(false); 527 Stop(false);
523 return; 528 return;
524 } 529 }
525 530
526 input_ = input; 531 input_ = input;
527 532
528 DoHistoryQuery(minimal_changes); 533 DoHistoryQuery(minimal_changes);
529 StartOrStopSuggestQuery(minimal_changes); 534 StartOrStopSuggestQuery(minimal_changes);
(...skipping 535 matching lines...) Expand 10 before | Expand all | Expand 10 after
1065 1070
1066 bool SearchProvider::IsTopMatchHighRankSearchForURL() const { 1071 bool SearchProvider::IsTopMatchHighRankSearchForURL() const {
1067 return input_.type() == AutocompleteInput::URL && 1072 return input_.type() == AutocompleteInput::URL &&
1068 matches_.front().relevance > CalculateRelevanceForVerbatim() && 1073 matches_.front().relevance > CalculateRelevanceForVerbatim() &&
1069 (matches_.front().type == AutocompleteMatchType::SEARCH_SUGGEST || 1074 (matches_.front().type == AutocompleteMatchType::SEARCH_SUGGEST ||
1070 matches_.front().type == 1075 matches_.front().type ==
1071 AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED || 1076 AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED ||
1072 matches_.front().type == AutocompleteMatchType::SEARCH_OTHER_ENGINE); 1077 matches_.front().type == AutocompleteMatchType::SEARCH_OTHER_ENGINE);
1073 } 1078 }
1074 1079
1075 bool SearchProvider::IsTopMatchNotInlinable() const { 1080 bool SearchProvider::IsTopMatchNotAllowedToBeDefaultMatch() const {
msw 2013/07/18 06:23:57 This function is almost what I'd expect Autocomple
Mark P 2013/07/21 20:31:05 Comment moot given the discussion you and Peter ha
msw 2013/07/18 06:23:57 Can you combine these two functions? It'd make mor
Mark P 2013/07/21 20:31:05 I see your desire, but I'd like to keep them separ
msw 2013/07/23 21:55:32 A combined function would check that either (1) or
Mark P 2013/07/26 16:48:13 Please suggest a good combined name. I can't thin
msw 2013/07/26 20:04:49 LacksValidDefaultMatch or HasValidDefaultMatch see
Mark P 2013/07/26 23:55:24 Used the first to parallel the other constraint te
1076 // Note: this test assumes the SEARCH_OTHER_ENGINE match corresponds to 1081 return !matches_.front().allowed_to_be_default_match;
1077 // the verbatim search query on the keyword engine. SearchProvider should 1082 }
1078 // not create any other match of type SEARCH_OTHER_ENGINE. 1083
1079 return 1084 bool SearchProvider::LacksDefaultMatch() const {
1080 matches_.front().type != AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED && 1085 for (ACMatches::const_iterator it = matches_.begin(); it != matches_.end();
1081 matches_.front().type != AutocompleteMatchType::SEARCH_OTHER_ENGINE && 1086 ++it) {
1082 matches_.front().inline_autocomplete_offset == string16::npos && 1087 if (it->allowed_to_be_default_match)
1083 matches_.front().fill_into_edit != input_.text(); 1088 return false;
1089 }
1090 return true;
1084 } 1091 }
1085 1092
1086 void SearchProvider::UpdateMatches() { 1093 void SearchProvider::UpdateMatches() {
1087 ConvertResultsToAutocompleteMatches(); 1094 ConvertResultsToAutocompleteMatches();
1088 1095
1089 // Check constraints that may be violated by suggested relevances. 1096 // Check constraints that may be violated by suggested relevances.
1090 if (!matches_.empty() && 1097 if (!matches_.empty() &&
1091 (default_results_.HasServerProvidedScores() || 1098 (default_results_.HasServerProvidedScores() ||
1092 keyword_results_.HasServerProvidedScores())) { 1099 keyword_results_.HasServerProvidedScores())) {
1093 // These blocks attempt to repair undesirable behavior by suggested 1100 // These blocks attempt to repair undesirable behavior by suggested
1094 // relevances with minimal impact, preserving other suggested relevances. 1101 // relevances with minimal impact, preserving other suggested relevances.
1095 if (IsTopMatchNavigationInKeywordMode()) { 1102 if (IsTopMatchNavigationInKeywordMode()) {
1096 // Correct the suggested relevance scores if the top match is a 1103 // Correct the suggested relevance scores if the top match is a
1097 // navigation in keyword mode, since inlining a navigation match 1104 // navigation in keyword mode, since inlining a navigation match
1098 // would break the user out of keyword mode. By the way, if the top 1105 // would break the user out of keyword mode. By the way, if the top
1099 // match is a non-keyword match (query or navsuggestion) in keyword 1106 // match is a non-keyword match (query or navsuggestion) in keyword
1100 // mode, the user would also break out of keyword mode. However, 1107 // mode, the user would also break out of keyword mode. However,
1101 // that situation is impossible given the current scoring paradigm 1108 // that situation is impossible given the current scoring paradigm
1102 // and the fact that only one search engine (Google) provides suggested 1109 // and the fact that only one search engine (Google) provides suggested
1103 // relevance scores at this time. 1110 // relevance scores at this time.
1104 DemoteKeywordNavigationMatchesPastTopQuery(); 1111 DemoteKeywordNavigationMatchesPastTopQuery();
1105 ConvertResultsToAutocompleteMatches(); 1112 ConvertResultsToAutocompleteMatches();
1106 DCHECK(!IsTopMatchNavigationInKeywordMode()); 1113 DCHECK(!IsTopMatchNavigationInKeywordMode());
1107 } 1114 }
1108 if (IsTopMatchScoreTooLow()) { 1115 if (!omnibox_will_reorder_for_legal_default_match_ &&
1116 IsTopMatchScoreTooLow()) {
1109 // Disregard the suggested verbatim relevance if the top score is below 1117 // Disregard the suggested verbatim relevance if the top score is below
1110 // the usual verbatim value. For example, a BarProvider may rely on 1118 // the usual verbatim value. For example, a BarProvider may rely on
1111 // SearchProvider's verbatim or inlineable matches for input "foo" to 1119 // SearchProvider's verbatim or inlineable matches for input "foo" (all
1112 // 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.
1113 default_results_.verbatim_relevance = -1; 1124 default_results_.verbatim_relevance = -1;
1114 keyword_results_.verbatim_relevance = -1; 1125 keyword_results_.verbatim_relevance = -1;
1115 ConvertResultsToAutocompleteMatches(); 1126 ConvertResultsToAutocompleteMatches();
1116 } 1127 }
1117 if (IsTopMatchHighRankSearchForURL()) { 1128 if (IsTopMatchHighRankSearchForURL()) {
1118 // Disregard the suggested search and verbatim relevances if the input 1129 // Disregard the suggested search and verbatim relevances if the input
1119 // 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.
1120 // For example, prevent a search for "foo.com" from outranking another 1131 // For example, prevent a search for "foo.com" from outranking another
1121 // 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".
1122 ApplyCalculatedSuggestRelevance(&keyword_results_.suggest_results); 1133 ApplyCalculatedSuggestRelevance(&keyword_results_.suggest_results);
1123 ApplyCalculatedSuggestRelevance(&default_results_.suggest_results); 1134 ApplyCalculatedSuggestRelevance(&default_results_.suggest_results);
1124 default_results_.verbatim_relevance = -1; 1135 default_results_.verbatim_relevance = -1;
1125 keyword_results_.verbatim_relevance = -1; 1136 keyword_results_.verbatim_relevance = -1;
1126 ConvertResultsToAutocompleteMatches(); 1137 ConvertResultsToAutocompleteMatches();
1127 } 1138 }
1128 if (IsTopMatchNotInlinable()) { 1139 if (omnibox_will_reorder_for_legal_default_match_ ?
1129 // Disregard suggested relevances if the top match is not a verbatim match 1140 LacksDefaultMatch() : IsTopMatchNotAllowedToBeDefaultMatch()) {
1130 // or inlinable. For example, input "foo" should not invoke a search for 1141 // Disregard suggested relevances if either:
1131 // "bar", which would happen if the "bar" search match outranked all other 1142 // * No matches are allowed to be the default match. SearchProvider is
1132 // matches. 1143 // supposed to return a legal default match for any input. We need
1144 // to make sure it does so. This constraint should be true always,
1145 // but we only need to check it if
1146 // |omnibox_will_reorder_for_legal_default_match_|. (If that were
1147 // false, the first part of the test above will suffice.)
msw 2013/07/18 06:23:57 I don't follow "the first part of the test above w
Mark P 2013/07/21 20:31:05 I rewrote this comment. It was confusing because
1148 // * The top match is not allowed to be the default match (i.e., it's not
1149 // either a verbatim match or inlinable). For example, input "foo"
1150 // should not invoke a search for "bar", which would happen if the
1151 // "bar" search match outranked all other matches. We only care
1152 // about this condition if the omnibox itself will not reorder
1153 // matches to put a legal default match on top.
1133 ApplyCalculatedRelevance(); 1154 ApplyCalculatedRelevance();
1134 ConvertResultsToAutocompleteMatches(); 1155 ConvertResultsToAutocompleteMatches();
1135 } 1156 }
1136 DCHECK(!IsTopMatchNavigationInKeywordMode()); 1157 DCHECK(!IsTopMatchNavigationInKeywordMode());
1137 DCHECK(!IsTopMatchScoreTooLow()); 1158 DCHECK(omnibox_will_reorder_for_legal_default_match_ ||
1159 !IsTopMatchScoreTooLow());
1138 DCHECK(!IsTopMatchHighRankSearchForURL()); 1160 DCHECK(!IsTopMatchHighRankSearchForURL());
1139 DCHECK(!IsTopMatchNotInlinable()); 1161 DCHECK(omnibox_will_reorder_for_legal_default_match_ ||
1162 !IsTopMatchNotAllowedToBeDefaultMatch());
1163 DCHECK(!LacksDefaultMatch());
1140 } 1164 }
1141 1165
1142 UpdateStarredStateOfMatches(); 1166 UpdateStarredStateOfMatches();
1143 UpdateDone(); 1167 UpdateDone();
1144 } 1168 }
1145 1169
1146 void SearchProvider::AddNavigationResultsToMatches( 1170 void SearchProvider::AddNavigationResultsToMatches(
1147 const NavigationResults& navigation_results, 1171 const NavigationResults& navigation_results,
1148 ACMatches* matches) { 1172 ACMatches* matches) {
1149 for (NavigationResults::const_iterator it = navigation_results.begin(); 1173 for (NavigationResults::const_iterator it = navigation_results.begin();
(...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after
1442 1466
1443 const std::string languages( 1467 const std::string languages(
1444 profile_->GetPrefs()->GetString(prefs::kAcceptLanguages)); 1468 profile_->GetPrefs()->GetString(prefs::kAcceptLanguages));
1445 const net::FormatUrlTypes format_types = 1469 const net::FormatUrlTypes format_types =
1446 net::kFormatUrlOmitAll & ~(trim_http ? 0 : net::kFormatUrlOmitHTTP); 1470 net::kFormatUrlOmitAll & ~(trim_http ? 0 : net::kFormatUrlOmitHTTP);
1447 match.fill_into_edit += 1471 match.fill_into_edit +=
1448 AutocompleteInput::FormattedStringWithEquivalentMeaning(navigation.url(), 1472 AutocompleteInput::FormattedStringWithEquivalentMeaning(navigation.url(),
1449 net::FormatUrl(navigation.url(), languages, format_types, 1473 net::FormatUrl(navigation.url(), languages, format_types,
1450 net::UnescapeRule::SPACES, NULL, NULL, 1474 net::UnescapeRule::SPACES, NULL, NULL,
1451 &inline_autocomplete_offset)); 1475 &inline_autocomplete_offset));
1452 if (!input_.prevent_inline_autocomplete()) 1476 if (!input_.prevent_inline_autocomplete()) {
1477 match.allowed_to_be_default_match =
1478 (inline_autocomplete_offset != string16::npos);
1453 match.inline_autocomplete_offset = inline_autocomplete_offset; 1479 match.inline_autocomplete_offset = inline_autocomplete_offset;
1480 }
1454 DCHECK((match.inline_autocomplete_offset == string16::npos) || 1481 DCHECK((match.inline_autocomplete_offset == string16::npos) ||
1455 (match.inline_autocomplete_offset <= match.fill_into_edit.length())); 1482 (match.inline_autocomplete_offset <= match.fill_into_edit.length()));
1456 1483
1457 match.contents = net::FormatUrl(navigation.url(), languages, 1484 match.contents = net::FormatUrl(navigation.url(), languages,
1458 format_types, net::UnescapeRule::SPACES, NULL, NULL, &match_start); 1485 format_types, net::UnescapeRule::SPACES, NULL, NULL, &match_start);
1459 // If the first match in the untrimmed string was inside a scheme that we 1486 // If the first match in the untrimmed string was inside a scheme that we
1460 // trimmed, look for a subsequent match. 1487 // trimmed, look for a subsequent match.
1461 if (match_start == string16::npos) 1488 if (match_start == string16::npos)
1462 match_start = match.contents.find(input); 1489 match_start = match.contents.find(input);
1463 // Safe if |match_start| is npos; also safe if the input is longer than the 1490 // Safe if |match_start| is npos; also safe if the input is longer than the
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
1516 it->set_relevance(max_query_relevance); 1543 it->set_relevance(max_query_relevance);
1517 it->set_relevance_from_server(relevance_from_server); 1544 it->set_relevance_from_server(relevance_from_server);
1518 } 1545 }
1519 } 1546 }
1520 1547
1521 void SearchProvider::UpdateDone() { 1548 void SearchProvider::UpdateDone() {
1522 // We're done when the timer isn't running, there are no suggest queries 1549 // We're done when the timer isn't running, there are no suggest queries
1523 // pending, and we're not waiting on Instant. 1550 // pending, and we're not waiting on Instant.
1524 done_ = !timer_.IsRunning() && (suggest_results_pending_ == 0); 1551 done_ = !timer_.IsRunning() && (suggest_results_pending_ == 0);
1525 } 1552 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698