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

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

Issue 471673002: Omnibox: Prevent Asynchronous Suggestions from Changing Default Match (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: add clarifying comment Created 6 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/base64.h" 10 #include "base/base64.h"
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after
253 match.keyword = providers_.default_provider(); 253 match.keyword = providers_.default_provider();
254 match.allowed_to_be_default_match = true; 254 match.allowed_to_be_default_match = true;
255 matches_.push_back(match); 255 matches_.push_back(match);
256 } 256 }
257 Stop(true); 257 Stop(true);
258 return; 258 return;
259 } 259 }
260 260
261 input_ = input; 261 input_ = input;
262 262
263 // If Start() is called without minimal_changes, it likely means the user
264 // has pressed a key. This is a good opportunity to change the inline
265 // autocompletion (if any). Restore the results to the original reply
266 // received from the server, thus clobbering any modification (if any) made
267 // to the results to demote an brand new async inline autocompletion.
268 if (!minimal_changes) {
269 default_results_ = orig_default_results_;
270 keyword_results_ = orig_keyword_results_;
271 }
272
263 DoHistoryQuery(minimal_changes); 273 DoHistoryQuery(minimal_changes);
264 DoAnswersQuery(input); 274 DoAnswersQuery(input);
265 StartOrStopSuggestQuery(minimal_changes); 275 StartOrStopSuggestQuery(minimal_changes);
266 UpdateMatches(); 276 UpdateMatches();
267 } 277 }
268 278
269 void SearchProvider::SortResults(bool is_keyword, 279 void SearchProvider::SortResults(bool is_keyword,
270 SearchSuggestionParser::Results* results) { 280 SearchSuggestionParser::Results* results) {
271 // Ignore suggested scores for non-keyword matches in keyword mode; if the 281 // Ignore suggested scores for non-keyword matches in keyword mode; if the
272 // server is allowed to score these, it could interfere with the user's 282 // server is allowed to score these, it could interfere with the user's
(...skipping 24 matching lines...) Expand all
297 return is_keyword ? providers_.GetKeywordProviderURL() 307 return is_keyword ? providers_.GetKeywordProviderURL()
298 : providers_.GetDefaultProviderURL(); 308 : providers_.GetDefaultProviderURL();
299 } 309 }
300 310
301 const AutocompleteInput SearchProvider::GetInput(bool is_keyword) const { 311 const AutocompleteInput SearchProvider::GetInput(bool is_keyword) const {
302 return is_keyword ? keyword_input_ : input_; 312 return is_keyword ? keyword_input_ : input_;
303 } 313 }
304 314
305 SearchSuggestionParser::Results* SearchProvider::GetResultsToFill( 315 SearchSuggestionParser::Results* SearchProvider::GetResultsToFill(
306 bool is_keyword) { 316 bool is_keyword) {
307 return is_keyword ? &keyword_results_ : &default_results_; 317 return is_keyword ? &orig_keyword_results_ : &orig_default_results_;
318 }
319
320 void SearchProvider::HandleReceivedResults(bool is_keyword) {
321 // The general strategy of this function:
322 // 1. Get the needed information from the previously-displayed results.
323 // 2. Copy the newly-received results over the previously-displayed ones.
324 // 3. Modify these results as necessary.
325
326 // 1. Extract needed information.
327 // Determine the previous inline autocompletion, if any.
328 // We store the inlined suggestion (if any) in one of the two following
329 // variables, leaving them blank if there is no inline suggestion or the
330 // inlined suggestion is not of that type.
331 base::string16 inlined_query_suggestion_match_contents;
332 GURL inlined_navsuggestion;
333 ACMatches::const_iterator first_match = FindTopMatch();
334 if ((first_match != matches_.end()) &&
335 !first_match->inline_autocompletion.empty()) {
336 // Identify if this match came from a query suggestion or a navsuggestion.
337 // In either case, extracts the identifying feature of the suggestion
338 // (query string or navigation url).
339 if (AutocompleteMatch::IsSearchType(first_match->type)) {
340 inlined_query_suggestion_match_contents = first_match->contents;
341 } else {
342 inlined_navsuggestion = first_match->destination_url;
343 }
344 }
345
346 // 2. Clobber the previous results.
347 SearchSuggestionParser::Results* results_from_server =
348 is_keyword ? &orig_keyword_results_ : &orig_default_results_;
349 SearchSuggestionParser::Results* results =
350 is_keyword ? &keyword_results_ : &default_results_;
351 (*results) = (*results_from_server);
352
353 // 3. Modify the results.
354 // Mark all results aside from the previous inline autocompletion as not
355 // allowed to be the default match.
356 for (SearchSuggestionParser::SuggestResults::iterator sug_it =
357 results->suggest_results.begin();
358 sug_it != results->suggest_results.end(); ++sug_it) {
359 if (sug_it->match_contents() !=
360 inlined_query_suggestion_match_contents) {
361 sug_it->set_never_allowed_to_be_default_match(true);
362 }
363 }
364 for (SearchSuggestionParser::NavigationResults::iterator nav_it =
365 results->navigation_results.begin();
366 nav_it != results->navigation_results.end(); ++nav_it) {
367 if (nav_it->url() != inlined_navsuggestion) {
368 nav_it->set_never_allowed_to_be_default_match(true);
369 }
370 }
308 } 371 }
309 372
310 bool SearchProvider::ShouldAppendExtraParams( 373 bool SearchProvider::ShouldAppendExtraParams(
311 const SearchSuggestionParser::SuggestResult& result) const { 374 const SearchSuggestionParser::SuggestResult& result) const {
312 return !result.from_keyword_provider() || 375 return !result.from_keyword_provider() ||
313 providers_.default_provider().empty(); 376 providers_.default_provider().empty();
314 } 377 }
315 378
316 void SearchProvider::StopSuggest() { 379 void SearchProvider::StopSuggest() {
317 // Increment the appropriate field in the histogram by the number of 380 // Increment the appropriate field in the histogram by the number of
318 // pending requests that were invalidated. 381 // pending requests that were invalidated.
319 for (int i = 0; i < suggest_results_pending_; ++i) 382 for (int i = 0; i < suggest_results_pending_; ++i)
320 LogOmniboxSuggestRequest(REQUEST_INVALIDATED); 383 LogOmniboxSuggestRequest(REQUEST_INVALIDATED);
321 suggest_results_pending_ = 0; 384 suggest_results_pending_ = 0;
322 timer_.Stop(); 385 timer_.Stop();
323 // Stop any in-progress URL fetches. 386 // Stop any in-progress URL fetches.
324 keyword_fetcher_.reset(); 387 keyword_fetcher_.reset();
325 default_fetcher_.reset(); 388 default_fetcher_.reset();
326 } 389 }
327 390
328 void SearchProvider::ClearAllResults() { 391 void SearchProvider::ClearAllResults() {
329 keyword_results_.Clear(); 392 keyword_results_.Clear();
330 default_results_.Clear(); 393 default_results_.Clear();
394 orig_keyword_results_.Clear();
395 orig_default_results_.Clear();
331 } 396 }
332 397
333 int SearchProvider::GetDefaultResultRelevance() const { 398 int SearchProvider::GetDefaultResultRelevance() const {
334 return -1; 399 return -1;
335 } 400 }
336 401
337 void SearchProvider::RecordDeletionResult(bool success) { 402 void SearchProvider::RecordDeletionResult(bool success) {
338 if (success) { 403 if (success) {
339 content::RecordAction( 404 content::RecordAction(
340 base::UserMetricsAction("Omnibox.ServerSuggestDelete.Success")); 405 base::UserMetricsAction("Omnibox.ServerSuggestDelete.Success"));
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after
617 } 682 }
618 683
619 void SearchProvider::ApplyCalculatedSuggestRelevance( 684 void SearchProvider::ApplyCalculatedSuggestRelevance(
620 SearchSuggestionParser::SuggestResults* list) { 685 SearchSuggestionParser::SuggestResults* list) {
621 for (size_t i = 0; i < list->size(); ++i) { 686 for (size_t i = 0; i < list->size(); ++i) {
622 SearchSuggestionParser::SuggestResult& result = (*list)[i]; 687 SearchSuggestionParser::SuggestResult& result = (*list)[i];
623 result.set_relevance( 688 result.set_relevance(
624 result.CalculateRelevance(input_, providers_.has_keyword_provider()) + 689 result.CalculateRelevance(input_, providers_.has_keyword_provider()) +
625 (list->size() - i - 1)); 690 (list->size() - i - 1));
626 result.set_relevance_from_server(false); 691 result.set_relevance_from_server(false);
692 result.set_never_allowed_to_be_default_match(false);
627 } 693 }
628 } 694 }
629 695
630 void SearchProvider::ApplyCalculatedNavigationRelevance( 696 void SearchProvider::ApplyCalculatedNavigationRelevance(
631 SearchSuggestionParser::NavigationResults* list) { 697 SearchSuggestionParser::NavigationResults* list) {
632 for (size_t i = 0; i < list->size(); ++i) { 698 for (size_t i = 0; i < list->size(); ++i) {
633 SearchSuggestionParser::NavigationResult& result = (*list)[i]; 699 SearchSuggestionParser::NavigationResult& result = (*list)[i];
634 result.set_relevance( 700 result.set_relevance(
635 result.CalculateRelevance(input_, providers_.has_keyword_provider()) + 701 result.CalculateRelevance(input_, providers_.has_keyword_provider()) +
636 (list->size() - i - 1)); 702 (list->size() - i - 1));
637 result.set_relevance_from_server(false); 703 result.set_relevance_from_server(false);
704 result.set_never_allowed_to_be_default_match(false);
638 } 705 }
639 } 706 }
640 707
641 net::URLFetcher* SearchProvider::CreateSuggestFetcher( 708 net::URLFetcher* SearchProvider::CreateSuggestFetcher(
642 int id, 709 int id,
643 const TemplateURL* template_url, 710 const TemplateURL* template_url,
644 const AutocompleteInput& input) { 711 const AutocompleteInput& input) {
645 if (!template_url || template_url->suggestions_url().empty()) 712 if (!template_url || template_url->suggestions_url().empty())
646 return NULL; 713 return NULL;
647 714
(...skipping 519 matching lines...) Expand 10 before | Expand all | Expand 10 after
1167 match.fill_into_edit.substr(inline_autocomplete_offset); 1234 match.fill_into_edit.substr(inline_autocomplete_offset);
1168 } 1235 }
1169 // An inlineable navsuggestion can only be the default match when there 1236 // An inlineable navsuggestion can only be the default match when there
1170 // is no keyword provider active, lest it appear first and break the user 1237 // is no keyword provider active, lest it appear first and break the user
1171 // out of keyword mode. It can also only be default if either the inline 1238 // out of keyword mode. It can also only be default if either the inline
1172 // autocompletion is empty or we're not preventing inline autocompletion. 1239 // autocompletion is empty or we're not preventing inline autocompletion.
1173 // Finally, if we have an inlineable navsuggestion with an inline completion 1240 // Finally, if we have an inlineable navsuggestion with an inline completion
1174 // that we're not preventing, make sure we didn't trim any whitespace. 1241 // that we're not preventing, make sure we didn't trim any whitespace.
1175 // We don't want to claim http://foo.com/bar is inlineable against the 1242 // We don't want to claim http://foo.com/bar is inlineable against the
1176 // input "foo.com/b ". 1243 // input "foo.com/b ".
1177 match.allowed_to_be_default_match = (prefix != NULL) && 1244 match.allowed_to_be_default_match =
1245 !navigation.never_allowed_to_be_default_match() &&
1246 (prefix != NULL) &&
1178 (providers_.GetKeywordProviderURL() == NULL) && 1247 (providers_.GetKeywordProviderURL() == NULL) &&
1179 (match.inline_autocompletion.empty() || 1248 (match.inline_autocompletion.empty() ||
1180 (!input_.prevent_inline_autocomplete() && !trimmed_whitespace)); 1249 (!input_.prevent_inline_autocomplete() && !trimmed_whitespace));
1181 match.EnsureUWYTIsAllowedToBeDefault( 1250 match.EnsureUWYTIsAllowedToBeDefault(
1182 input_.canonicalized_url(), providers_.template_url_service()); 1251 input_.canonicalized_url(), providers_.template_url_service());
1183 1252
1184 match.contents = navigation.match_contents(); 1253 match.contents = navigation.match_contents();
1185 match.contents_class = navigation.match_contents_class(); 1254 match.contents_class = navigation.match_contents_class();
1186 match.description = navigation.description(); 1255 match.description = navigation.description();
1187 AutocompleteMatch::ClassifyMatchInString(input, match.description, 1256 AutocompleteMatch::ClassifyMatchInString(input, match.description,
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
1241 last_answer_seen_.query_type = match->answer_type; 1310 last_answer_seen_.query_type = match->answer_type;
1242 } 1311 }
1243 1312
1244 void SearchProvider::DoAnswersQuery(const AutocompleteInput& input) { 1313 void SearchProvider::DoAnswersQuery(const AutocompleteInput& input) {
1245 // If the query text starts with trimmed input, this is valid prefetch data. 1314 // If the query text starts with trimmed input, this is valid prefetch data.
1246 prefetch_data_ = StartsWith(last_answer_seen_.full_query_text, 1315 prefetch_data_ = StartsWith(last_answer_seen_.full_query_text,
1247 base::CollapseWhitespace(input.text(), false), 1316 base::CollapseWhitespace(input.text(), false),
1248 false) ? 1317 false) ?
1249 last_answer_seen_ : AnswersQueryData(); 1318 last_answer_seen_ : AnswersQueryData();
1250 } 1319 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698