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

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: better resolve rebase 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 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
163 // functions are currently in sync, but there's no reason we 163 // functions are currently in sync, but there's no reason we
164 // couldn't decide in the future to score verbatim matches 164 // couldn't decide in the future to score verbatim matches
165 // differently for extension and non-extension keywords. If you 165 // differently for extension and non-extension keywords. If you
166 // make such a change, however, you should update this comment to 166 // make such a change, however, you should update this comment to
167 // describe it, so it's clear why the functions diverge. 167 // describe it, so it's clear why the functions diverge.
168 if (prefer_keyword) 168 if (prefer_keyword)
169 return 1500; 169 return 1500;
170 return (type == metrics::OmniboxInputType::QUERY) ? 1450 : 1100; 170 return (type == metrics::OmniboxInputType::QUERY) ? 1450 : 1100;
171 } 171 }
172 172
173 // static
174 void SearchProvider::RemoveOrReviseOldResultsForOneProvider(
175 bool minimal_changes, SearchSuggestionParser::Results* results) {
176 // When called without |minimal_changes|, it likely means the user has
177 // pressed a key. Revise the cached results appropriately.
178 if (!minimal_changes) {
179 for (SearchSuggestionParser::SuggestResults::iterator sug_it =
180 results->suggest_results.begin();
181 sug_it != results->suggest_results.end(); ++sug_it) {
182 sug_it->set_received_after_last_keystroke(false);
183 }
184 for (SearchSuggestionParser::NavigationResults::iterator nav_it =
185 results->navigation_results.begin();
186 nav_it != results->navigation_results.end(); ++nav_it) {
187 nav_it->set_received_after_last_keystroke(false);
188 }
189 }
190 }
191
192 // static
193 ACMatches::iterator SearchProvider::FindTopMatch(ACMatches* matches) {
194 ACMatches::iterator it = matches->begin();
195 while ((it != matches->end()) && !it->allowed_to_be_default_match)
196 ++it;
197 return it;
198 }
199
173 void SearchProvider::Start(const AutocompleteInput& input, 200 void SearchProvider::Start(const AutocompleteInput& input,
174 bool minimal_changes) { 201 bool minimal_changes) {
175 // Do our best to load the model as early as possible. This will reduce 202 // Do our best to load the model as early as possible. This will reduce
176 // odds of having the model not ready when really needed (a non-empty input). 203 // odds of having the model not ready when really needed (a non-empty input).
177 TemplateURLService* model = providers_.template_url_service(); 204 TemplateURLService* model = providers_.template_url_service();
178 DCHECK(model); 205 DCHECK(model);
179 model->Load(); 206 model->Load();
180 207
181 matches_.clear(); 208 matches_.clear();
182 field_trial_triggered_ = false; 209 field_trial_triggered_ = false;
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after
385 UMA_HISTOGRAM_TIMES("Omnibox.SuggestRequest.Success.GoogleResponseTime", 412 UMA_HISTOGRAM_TIMES("Omnibox.SuggestRequest.Success.GoogleResponseTime",
386 elapsed_time); 413 elapsed_time);
387 } else { 414 } else {
388 UMA_HISTOGRAM_TIMES("Omnibox.SuggestRequest.Failure.GoogleResponseTime", 415 UMA_HISTOGRAM_TIMES("Omnibox.SuggestRequest.Failure.GoogleResponseTime",
389 elapsed_time); 416 elapsed_time);
390 } 417 }
391 } 418 }
392 } 419 }
393 420
394 void SearchProvider::UpdateMatches() { 421 void SearchProvider::UpdateMatches() {
422 PersistGoodResultsForOneProvider(&default_results_);
423 PersistGoodResultsForOneProvider(&keyword_results_);
395 ConvertResultsToAutocompleteMatches(); 424 ConvertResultsToAutocompleteMatches();
396 425
397 // Check constraints that may be violated by suggested relevances. 426 // Check constraints that may be violated by suggested relevances.
398 if (!matches_.empty() && 427 if (!matches_.empty() &&
399 (default_results_.HasServerProvidedScores() || 428 (default_results_.HasServerProvidedScores() ||
400 keyword_results_.HasServerProvidedScores())) { 429 keyword_results_.HasServerProvidedScores())) {
401 // These blocks attempt to repair undesirable behavior by suggested 430 // These blocks attempt to repair undesirable behavior by suggested
402 // relevances with minimal impact, preserving other suggested relevances. 431 // relevances with minimal impact, preserving other suggested relevances.
403 432
404 if (!HasKeywordDefaultMatchInKeywordMode()) { 433 if ((providers_.GetKeywordProviderURL() != NULL) &&
434 (FindTopMatch() == matches_.end())) {
405 // In keyword mode, disregard the keyword verbatim suggested relevance 435 // In keyword mode, disregard the keyword verbatim suggested relevance
406 // if necessary so there at least one keyword match that's allowed to 436 // if necessary, so at least one match is allowed to be default. Give
407 // be the default match. 437 // it the lowest non-zero score to best reflect what the server desired.
408 keyword_results_.verbatim_relevance = -1; 438 keyword_results_.verbatim_relevance = 1;
409 ConvertResultsToAutocompleteMatches(); 439 ConvertResultsToAutocompleteMatches();
410 } 440 }
411 if (IsTopMatchSearchWithURLInput()) { 441 if (IsTopMatchSearchWithURLInput()) {
412 // Disregard the suggested search and verbatim relevances if the input 442 // Disregard the suggested search and verbatim relevances if the input
413 // type is URL and the top match is a highly-ranked search suggestion. 443 // type is URL and the top match is a highly-ranked search suggestion.
414 // For example, prevent a search for "foo.com" from outranking another 444 // For example, prevent a search for "foo.com" from outranking another
415 // provider's navigation for "foo.com" or "foo.com/url_from_history". 445 // provider's navigation for "foo.com" or "foo.com/url_from_history".
416 ApplyCalculatedSuggestRelevance(&keyword_results_.suggest_results); 446 ApplyCalculatedSuggestRelevance(&keyword_results_.suggest_results);
417 ApplyCalculatedSuggestRelevance(&default_results_.suggest_results); 447 ApplyCalculatedSuggestRelevance(&default_results_.suggest_results);
418 default_results_.verbatim_relevance = -1; 448 default_results_.verbatim_relevance = -1;
419 keyword_results_.verbatim_relevance = -1; 449 keyword_results_.verbatim_relevance = -1;
420 ConvertResultsToAutocompleteMatches(); 450 ConvertResultsToAutocompleteMatches();
421 } 451 }
422 if (FindTopMatch() == matches_.end()) { 452 if (FindTopMatch() == matches_.end()) {
423 // Guarantee that SearchProvider returns a legal default match. (The 453 // Guarantee that SearchProvider returns a legal default match. (The
424 // omnibox always needs at least one legal default match, and it relies 454 // omnibox always needs at least one legal default match, and it relies
425 // on SearchProvider to always return one.) 455 // on SearchProvider to always return one.) Give them the lowest
426 ApplyCalculatedRelevance(); 456 // non-zero scores to best reflect what the server desired.
457 default_results_.verbatim_relevance = 1;
458 keyword_results_.verbatim_relevance = 1;
427 ConvertResultsToAutocompleteMatches(); 459 ConvertResultsToAutocompleteMatches();
428 } 460 }
429 DCHECK(HasKeywordDefaultMatchInKeywordMode());
430 DCHECK(!IsTopMatchSearchWithURLInput()); 461 DCHECK(!IsTopMatchSearchWithURLInput());
431 DCHECK(FindTopMatch() != matches_.end()); 462 DCHECK(FindTopMatch() != matches_.end());
432 } 463 }
433 UMA_HISTOGRAM_CUSTOM_COUNTS( 464 UMA_HISTOGRAM_CUSTOM_COUNTS(
434 "Omnibox.SearchProviderMatches", matches_.size(), 1, 6, 7); 465 "Omnibox.SearchProviderMatches", matches_.size(), 1, 6, 7);
435 466
436 const TemplateURL* keyword_url = providers_.GetKeywordProviderURL(); 467 // Record the inlined suggestion (if any) for future use.
Mark P 2014/08/15 20:04:38 This was clobbered in the refactoring changelist.
437 if ((keyword_url != NULL) && HasKeywordDefaultMatchInKeywordMode()) { 468 inlined_query_suggestion_match_contents_ = base::string16();
438 // If there is a keyword match that is allowed to be the default match, 469 inlined_navsuggestion_ = GURL();
439 // then prohibit default provider matches from being the default match lest 470 ACMatches::const_iterator first_match = FindTopMatch();
440 // such matches cause the user to break out of keyword mode. 471 if ((first_match != matches_.end()) &&
441 for (ACMatches::iterator it = matches_.begin(); it != matches_.end(); 472 !first_match->inline_autocompletion.empty()) {
442 ++it) { 473 // Identify if this match came from a query suggestion or a navsuggestion.
443 if (it->keyword != keyword_url->keyword()) 474 // In either case, extracts the identifying feature of the suggestion
444 it->allowed_to_be_default_match = false; 475 // (query string or navigation url).
476 if (AutocompleteMatch::IsSearchType(first_match->type)) {
477 inlined_query_suggestion_match_contents_ = first_match->contents;
478 } else {
479 inlined_navsuggestion_ = first_match->destination_url;
445 } 480 }
446 } 481 }
482
447 UpdateDone(); 483 UpdateDone();
448 } 484 }
449 485
450 void SearchProvider::Run() { 486 void SearchProvider::Run() {
451 // Start a new request with the current input. 487 // Start a new request with the current input.
452 suggest_results_pending_ = 0; 488 suggest_results_pending_ = 0;
453 time_suggest_request_sent_ = base::TimeTicks::Now(); 489 time_suggest_request_sent_ = base::TimeTicks::Now();
454 490
455 default_fetcher_.reset(CreateSuggestFetcher(kDefaultProviderURLFetcherID, 491 default_fetcher_.reset(CreateSuggestFetcher(kDefaultProviderURLFetcherID,
456 providers_.GetDefaultProviderURL(), input_)); 492 providers_.GetDefaultProviderURL(), input_));
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
527 (!default_results_.suggest_results.empty() || 563 (!default_results_.suggest_results.empty() ||
528 !default_results_.navigation_results.empty() || 564 !default_results_.navigation_results.empty() ||
529 !keyword_results_.suggest_results.empty() || 565 !keyword_results_.suggest_results.empty() ||
530 !keyword_results_.navigation_results.empty() || 566 !keyword_results_.navigation_results.empty() ||
531 (!done_ && input_.want_asynchronous_matches()))) 567 (!done_ && input_.want_asynchronous_matches())))
532 return; 568 return;
533 569
534 // We can't keep running any previous query, so halt it. 570 // We can't keep running any previous query, so halt it.
535 StopSuggest(); 571 StopSuggest();
536 572
537 // Remove existing results that cannot inline autocomplete the new input. 573 RemoveOrReviseOldResults(minimal_changes);
538 RemoveAllStaleResults();
539 574
540 // Update the content classifications of remaining results so they look good 575 // Update the content classifications of remaining results so they look good
541 // against the current input. 576 // against the current input.
542 UpdateMatchContentsClass(input_.text(), &default_results_); 577 UpdateMatchContentsClass(input_.text(), &default_results_);
543 if (!keyword_input_.text().empty()) 578 if (!keyword_input_.text().empty())
544 UpdateMatchContentsClass(keyword_input_.text(), &keyword_results_); 579 UpdateMatchContentsClass(keyword_input_.text(), &keyword_results_);
545 580
546 // We can't start a new query if we're only allowed synchronous results. 581 // We can't start a new query if we're only allowed synchronous results.
547 if (!input_.want_asynchronous_matches()) 582 if (!input_.want_asynchronous_matches())
548 return; 583 return;
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
612 // Don't send anything for https except the hostname. Hostnames are OK 647 // Don't send anything for https except the hostname. Hostnames are OK
613 // because they are visible when the TCP connection is established, but the 648 // because they are visible when the TCP connection is established, but the
614 // specific path may reveal private information. 649 // specific path may reveal private information.
615 if (LowerCaseEqualsASCII(input_.scheme(), url::kHttpsScheme) && 650 if (LowerCaseEqualsASCII(input_.scheme(), url::kHttpsScheme) &&
616 parts.path.is_nonempty()) 651 parts.path.is_nonempty())
617 return false; 652 return false;
618 653
619 return true; 654 return true;
620 } 655 }
621 656
622 void SearchProvider::RemoveAllStaleResults() { 657 void SearchProvider::RemoveOrReviseOldResults(bool minimal_changes) {
623 if (keyword_input_.text().empty()) { 658 if (keyword_input_.text().empty()) {
624 // User is either in keyword mode with a blank input or out of 659 // User is either in keyword mode with a blank input or out of
625 // keyword mode entirely. 660 // keyword mode entirely.
626 keyword_results_.Clear(); 661 keyword_results_.Clear();
627 } 662 }
663 RemoveOrReviseOldResultsForOneProvider(minimal_changes, &default_results_);
664 RemoveOrReviseOldResultsForOneProvider(minimal_changes, &keyword_results_);
628 } 665 }
629 666
630 void SearchProvider::ApplyCalculatedRelevance() { 667 void SearchProvider::PersistGoodResultsForOneProvider(
msw 2014/08/15 21:04:37 Why do we need this at all? Isn't "RemoveOrReviseO
Mark P 2014/08/15 22:09:21 This is definitely needed. Without this function
msw 2014/08/15 23:31:10 The new name is good, thanks for explaining the ne
631 ApplyCalculatedSuggestRelevance(&keyword_results_.suggest_results); 668 SearchSuggestionParser::Results* results) {
632 ApplyCalculatedSuggestRelevance(&default_results_.suggest_results); 669 // Mark the result corresponding to the previous inline autocompletion as
633 ApplyCalculatedNavigationRelevance(&keyword_results_.navigation_results); 670 // having been received on a previous keystroke (as indeed it must have
msw 2014/08/15 21:04:37 nit: s/on a previous/before the last/
Mark P 2014/08/15 22:09:21 Done.
634 ApplyCalculatedNavigationRelevance(&default_results_.navigation_results); 671 // because we prohibit newly-received results from becoming the inline
msw 2014/08/15 21:04:37 I don't know how this (indeed it must have...) com
Mark P 2014/08/15 22:09:21 Removed the comment. I think the comment by the f
635 default_results_.verbatim_relevance = -1; 672 // autocompletion).
636 keyword_results_.verbatim_relevance = -1; 673 if (!inlined_query_suggestion_match_contents_.empty()) {
674 for (SearchSuggestionParser::SuggestResults::iterator sug_it =
675 results->suggest_results.begin();
676 sug_it != results->suggest_results.end(); ++sug_it) {
677 if (sug_it->match_contents() ==
678 inlined_query_suggestion_match_contents_)
679 sug_it->set_received_after_last_keystroke(false);
680 }
681 }
682 if (inlined_navsuggestion_.is_valid()) {
683 for (SearchSuggestionParser::NavigationResults::iterator nav_it =
684 results->navigation_results.begin();
685 nav_it != results->navigation_results.end(); ++nav_it) {
686 if (nav_it->url() == inlined_navsuggestion_)
687 nav_it->set_received_after_last_keystroke(false);
688 }
689 }
637 } 690 }
638 691
639 void SearchProvider::ApplyCalculatedSuggestRelevance( 692 void SearchProvider::ApplyCalculatedSuggestRelevance(
640 SearchSuggestionParser::SuggestResults* list) { 693 SearchSuggestionParser::SuggestResults* list) {
641 for (size_t i = 0; i < list->size(); ++i) { 694 for (size_t i = 0; i < list->size(); ++i) {
642 SearchSuggestionParser::SuggestResult& result = (*list)[i]; 695 SearchSuggestionParser::SuggestResult& result = (*list)[i];
643 result.set_relevance( 696 result.set_relevance(
644 result.CalculateRelevance(input_, providers_.has_keyword_provider()) + 697 result.CalculateRelevance(input_, providers_.has_keyword_provider()) +
645 (list->size() - i - 1)); 698 (list->size() - i - 1));
646 result.set_relevance_from_server(false); 699 result.set_relevance_from_server(false);
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
723 keyword_results_.suggest_results.empty() ? 776 keyword_results_.suggest_results.empty() ?
724 TemplateURLRef::NO_SUGGESTIONS_AVAILABLE : 777 TemplateURLRef::NO_SUGGESTIONS_AVAILABLE :
725 TemplateURLRef::NO_SUGGESTION_CHOSEN; 778 TemplateURLRef::NO_SUGGESTION_CHOSEN;
726 779
727 bool relevance_from_server; 780 bool relevance_from_server;
728 int verbatim_relevance = GetVerbatimRelevance(&relevance_from_server); 781 int verbatim_relevance = GetVerbatimRelevance(&relevance_from_server);
729 int did_not_accept_default_suggestion = 782 int did_not_accept_default_suggestion =
730 default_results_.suggest_results.empty() ? 783 default_results_.suggest_results.empty() ?
731 TemplateURLRef::NO_SUGGESTIONS_AVAILABLE : 784 TemplateURLRef::NO_SUGGESTIONS_AVAILABLE :
732 TemplateURLRef::NO_SUGGESTION_CHOSEN; 785 TemplateURLRef::NO_SUGGESTION_CHOSEN;
786 const TemplateURL* keyword_url = providers_.GetKeywordProviderURL();
733 if (verbatim_relevance > 0) { 787 if (verbatim_relevance > 0) {
734 const base::string16& trimmed_verbatim = 788 const base::string16& trimmed_verbatim =
735 base::CollapseWhitespace(input_.text(), false); 789 base::CollapseWhitespace(input_.text(), false);
736 790
737 // Verbatim results don't get suggestions and hence, answers. 791 // Verbatim results don't get suggestions and hence, answers.
738 // Scan previous matches if the last answer-bearing suggestion matches 792 // Scan previous matches if the last answer-bearing suggestion matches
739 // verbatim, and if so, copy over answer contents. 793 // verbatim, and if so, copy over answer contents.
740 base::string16 answer_contents; 794 base::string16 answer_contents;
741 base::string16 answer_type; 795 base::string16 answer_type;
742 for (ACMatches::iterator it = matches_.begin(); it != matches_.end(); 796 for (ACMatches::iterator it = matches_.begin(); it != matches_.end();
743 ++it) { 797 ++it) {
744 if (!it->answer_contents.empty() && 798 if (!it->answer_contents.empty() &&
745 it->fill_into_edit == trimmed_verbatim) { 799 it->fill_into_edit == trimmed_verbatim) {
746 answer_contents = it->answer_contents; 800 answer_contents = it->answer_contents;
747 answer_type = it->answer_type; 801 answer_type = it->answer_type;
748 break; 802 break;
749 } 803 }
750 } 804 }
751 805
752 SearchSuggestionParser::SuggestResult verbatim( 806 SearchSuggestionParser::SuggestResult verbatim(
753 trimmed_verbatim, AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED, 807 trimmed_verbatim, AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED,
754 trimmed_verbatim, base::string16(), base::string16(), answer_contents, 808 trimmed_verbatim, base::string16(), base::string16(), answer_contents,
755 answer_type, std::string(), std::string(), false, verbatim_relevance, 809 answer_type, std::string(), std::string(), false, verbatim_relevance,
756 relevance_from_server, false, trimmed_verbatim); 810 relevance_from_server, false, trimmed_verbatim);
757 AddMatchToMap(verbatim, std::string(), did_not_accept_default_suggestion, 811 AddMatchToMap(verbatim, std::string(), did_not_accept_default_suggestion,
758 false, &map); 812 false, keyword_url != NULL, &map);
759 } 813 }
760 if (!keyword_input_.text().empty()) { 814 if (!keyword_input_.text().empty()) {
761 const TemplateURL* keyword_url = providers_.GetKeywordProviderURL();
762 // We only create the verbatim search query match for a keyword 815 // We only create the verbatim search query match for a keyword
763 // if it's not an extension keyword. Extension keywords are handled 816 // if it's not an extension keyword. Extension keywords are handled
764 // in KeywordProvider::Start(). (Extensions are complicated...) 817 // in KeywordProvider::Start(). (Extensions are complicated...)
765 // Note: in this provider, SEARCH_OTHER_ENGINE must correspond 818 // Note: in this provider, SEARCH_OTHER_ENGINE must correspond
766 // to the keyword verbatim search query. Do not create other matches 819 // to the keyword verbatim search query. Do not create other matches
767 // of type SEARCH_OTHER_ENGINE. 820 // of type SEARCH_OTHER_ENGINE.
768 if (keyword_url && 821 if (keyword_url &&
769 (keyword_url->GetType() != TemplateURL::OMNIBOX_API_EXTENSION)) { 822 (keyword_url->GetType() != TemplateURL::OMNIBOX_API_EXTENSION)) {
770 bool keyword_relevance_from_server; 823 bool keyword_relevance_from_server;
771 const int keyword_verbatim_relevance = 824 const int keyword_verbatim_relevance =
772 GetKeywordVerbatimRelevance(&keyword_relevance_from_server); 825 GetKeywordVerbatimRelevance(&keyword_relevance_from_server);
773 if (keyword_verbatim_relevance > 0) { 826 if (keyword_verbatim_relevance > 0) {
774 const base::string16& trimmed_verbatim = 827 const base::string16& trimmed_verbatim =
775 base::CollapseWhitespace(keyword_input_.text(), false); 828 base::CollapseWhitespace(keyword_input_.text(), false);
776 SearchSuggestionParser::SuggestResult verbatim( 829 SearchSuggestionParser::SuggestResult verbatim(
777 trimmed_verbatim, AutocompleteMatchType::SEARCH_OTHER_ENGINE, 830 trimmed_verbatim, AutocompleteMatchType::SEARCH_OTHER_ENGINE,
778 trimmed_verbatim, base::string16(), base::string16(), 831 trimmed_verbatim, base::string16(), base::string16(),
779 base::string16(), base::string16(), std::string(), std::string(), 832 base::string16(), base::string16(), std::string(), std::string(),
780 true, keyword_verbatim_relevance, keyword_relevance_from_server, 833 true, keyword_verbatim_relevance, keyword_relevance_from_server,
781 false, trimmed_verbatim); 834 false, trimmed_verbatim);
782 AddMatchToMap(verbatim, std::string(), 835 AddMatchToMap(verbatim, std::string(),
783 did_not_accept_keyword_suggestion, false, &map); 836 did_not_accept_keyword_suggestion, false, true, &map);
784 } 837 }
785 } 838 }
786 } 839 }
787 AddHistoryResultsToMap(keyword_history_results_, true, 840 AddHistoryResultsToMap(keyword_history_results_, true,
788 did_not_accept_keyword_suggestion, &map); 841 did_not_accept_keyword_suggestion, &map);
789 AddHistoryResultsToMap(default_history_results_, false, 842 AddHistoryResultsToMap(default_history_results_, false,
790 did_not_accept_default_suggestion, &map); 843 did_not_accept_default_suggestion, &map);
791 844
792 AddSuggestResultsToMap(keyword_results_.suggest_results, 845 AddSuggestResultsToMap(keyword_results_.suggest_results,
793 keyword_results_.metadata, &map); 846 keyword_results_.metadata, &map);
794 AddSuggestResultsToMap(default_results_.suggest_results, 847 AddSuggestResultsToMap(default_results_.suggest_results,
795 default_results_.metadata, &map); 848 default_results_.metadata, &map);
796 849
797 ACMatches matches; 850 ACMatches matches;
798 for (MatchMap::const_iterator i(map.begin()); i != map.end(); ++i) 851 for (MatchMap::const_iterator i(map.begin()); i != map.end(); ++i)
799 matches.push_back(i->second); 852 matches.push_back(i->second);
800 853
801 AddNavigationResultsToMatches(keyword_results_.navigation_results, &matches); 854 AddNavigationResultsToMatches(keyword_results_.navigation_results, &matches);
802 AddNavigationResultsToMatches(default_results_.navigation_results, &matches); 855 AddNavigationResultsToMatches(default_results_.navigation_results, &matches);
803 856
804 // Now add the most relevant matches to |matches_|. We take up to kMaxMatches 857 // Now add the most relevant matches to |matches_|. We take up to kMaxMatches
805 // suggest/navsuggest matches, regardless of origin. If Instant Extended is 858 // suggest/navsuggest matches, regardless of origin. We always include in
806 // enabled and we have server-provided (and thus hopefully more accurate) 859 // that set a legal default match if possible. If Instant Extended is enabled
807 // scores for some suggestions, we allow more of those, until we reach 860 // and we have server-provided (and thus hopefully more accurate) scores for
861 // some suggestions, we allow more of those, until we reach
808 // AutocompleteResult::kMaxMatches total matches (that is, enough to fill the 862 // AutocompleteResult::kMaxMatches total matches (that is, enough to fill the
809 // whole popup). 863 // whole popup).
810 // 864 //
811 // We will always return any verbatim matches, no matter how we obtained their 865 // We will always return any verbatim matches, no matter how we obtained their
812 // scores, unless we have already accepted AutocompleteResult::kMaxMatches 866 // scores, unless we have already accepted AutocompleteResult::kMaxMatches
813 // higher-scoring matches under the conditions above. 867 // higher-scoring matches under the conditions above.
814 std::sort(matches.begin(), matches.end(), &AutocompleteMatch::MoreRelevant); 868 std::sort(matches.begin(), matches.end(), &AutocompleteMatch::MoreRelevant);
815 matches_.clear(); 869 matches_.clear();
870 // Guarantee that if there's a legal default match anywhere in the result
msw 2014/08/15 21:04:37 Why is this needed now? I thought the |allowed_to_
Mark P 2014/08/15 22:09:21 This is needed because AutocompleteResult enforces
msw 2014/08/15 23:31:10 My question is "why do we need to rotate the match
Mark P 2014/08/15 23:50:15 This call to rotate does a remove from current loc
871 // set that it'll get returned by moving the default match to the front
872 // of the list.
873 ACMatches::iterator default_match = FindTopMatch(&matches);
874 if (default_match != matches.end()) {
msw 2014/08/15 21:04:37 nit: remove curly braces.
Mark P 2014/08/15 22:09:21 Done.
875 std::rotate(matches.begin(), default_match, default_match + 1);
876 }
816 877
817 size_t num_suggestions = 0; 878 size_t num_suggestions = 0;
818 for (ACMatches::const_iterator i(matches.begin()); 879 for (ACMatches::const_iterator i(matches.begin());
819 (i != matches.end()) && 880 (i != matches.end()) &&
820 (matches_.size() < AutocompleteResult::kMaxMatches); 881 (matches_.size() < AutocompleteResult::kMaxMatches);
821 ++i) { 882 ++i) {
822 // SEARCH_OTHER_ENGINE is only used in the SearchProvider for the keyword 883 // SEARCH_OTHER_ENGINE is only used in the SearchProvider for the keyword
823 // verbatim result, so this condition basically means "if this match is a 884 // verbatim result, so this condition basically means "if this match is a
824 // suggestion of some sort". 885 // suggestion of some sort".
825 if ((i->type != AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED) && 886 if ((i->type != AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED) &&
826 (i->type != AutocompleteMatchType::SEARCH_OTHER_ENGINE)) { 887 (i->type != AutocompleteMatchType::SEARCH_OTHER_ENGINE)) {
827 // If we've already hit the limit on non-server-scored suggestions, and 888 // If we've already hit the limit on non-server-scored suggestions, and
828 // this isn't a server-scored suggestion we can add, skip it. 889 // this isn't a server-scored suggestion we can add, skip it.
829 if ((num_suggestions >= kMaxMatches) && 890 if ((num_suggestions >= kMaxMatches) &&
830 (!chrome::IsInstantExtendedAPIEnabled() || 891 (!chrome::IsInstantExtendedAPIEnabled() ||
831 (i->GetAdditionalInfo(kRelevanceFromServerKey) != kTrue))) { 892 (i->GetAdditionalInfo(kRelevanceFromServerKey) != kTrue))) {
832 continue; 893 continue;
833 } 894 }
834 895
835 ++num_suggestions; 896 ++num_suggestions;
836 } 897 }
837 898
838 matches_.push_back(*i); 899 matches_.push_back(*i);
839 } 900 }
840 UMA_HISTOGRAM_TIMES("Omnibox.SearchProvider.ConvertResultsTime", 901 UMA_HISTOGRAM_TIMES("Omnibox.SearchProvider.ConvertResultsTime",
841 base::TimeTicks::Now() - start_time); 902 base::TimeTicks::Now() - start_time);
842 } 903 }
843 904
844 ACMatches::const_iterator SearchProvider::FindTopMatch() const { 905 ACMatches::const_iterator SearchProvider::FindTopMatch() const {
msw 2014/08/15 21:04:38 Remove this, use FindTopMatch(&matches_) at callsi
Mark P 2014/08/15 22:09:21 I can't do that because some callsites are const f
msw 2014/08/15 23:31:10 I guess leave the duplication for now, unless you
Mark P 2014/08/15 23:50:15 Acknowledged. (I can't remove the rotate call.)
845 ACMatches::const_iterator it = matches_.begin(); 906 ACMatches::const_iterator it = matches_.begin();
846 while ((it != matches_.end()) && !it->allowed_to_be_default_match) 907 while ((it != matches_.end()) && !it->allowed_to_be_default_match)
847 ++it; 908 ++it;
848 return it; 909 return it;
849 } 910 }
850 911
851 bool SearchProvider::HasKeywordDefaultMatchInKeywordMode() const {
Mark P 2014/08/15 20:04:38 Deleted in refactoring changelist.
852 const TemplateURL* keyword_url = providers_.GetKeywordProviderURL();
853 // If the user is not in keyword mode, return true to say that this
854 // constraint is not violated.
855 if (keyword_url == NULL)
856 return true;
857 for (ACMatches::const_iterator it = matches_.begin(); it != matches_.end();
858 ++it) {
859 if ((it->keyword == keyword_url->keyword()) &&
860 it->allowed_to_be_default_match)
861 return true;
862 }
863 return false;
864 }
865
866 bool SearchProvider::IsTopMatchSearchWithURLInput() const { 912 bool SearchProvider::IsTopMatchSearchWithURLInput() const {
867 ACMatches::const_iterator first_match = FindTopMatch(); 913 ACMatches::const_iterator first_match = FindTopMatch();
868 return (input_.type() == metrics::OmniboxInputType::URL) && 914 return (input_.type() == metrics::OmniboxInputType::URL) &&
869 (first_match != matches_.end()) && 915 (first_match != matches_.end()) &&
870 (first_match->relevance > CalculateRelevanceForVerbatim()) && 916 (first_match->relevance > CalculateRelevanceForVerbatim()) &&
871 (first_match->type != AutocompleteMatchType::NAVSUGGEST) && 917 (first_match->type != AutocompleteMatchType::NAVSUGGEST) &&
872 (first_match->type != AutocompleteMatchType::NAVSUGGEST_PERSONALIZED); 918 (first_match->type != AutocompleteMatchType::NAVSUGGEST_PERSONALIZED);
873 } 919 }
874 920
875 void SearchProvider::AddNavigationResultsToMatches( 921 void SearchProvider::AddNavigationResultsToMatches(
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
915 if ((scored_results.front().relevance() < 1200) || 961 if ((scored_results.front().relevance() < 1200) ||
916 !HasMultipleWords(scored_results.front().suggestion())) 962 !HasMultipleWords(scored_results.front().suggestion()))
917 scored_results.clear(); // Didn't detect the case above, score normally. 963 scored_results.clear(); // Didn't detect the case above, score normally.
918 } 964 }
919 if (scored_results.empty()) 965 if (scored_results.empty())
920 scored_results = ScoreHistoryResults(results, prevent_inline_autocomplete, 966 scored_results = ScoreHistoryResults(results, prevent_inline_autocomplete,
921 input_multiple_words, input_text, 967 input_multiple_words, input_text,
922 is_keyword); 968 is_keyword);
923 for (SearchSuggestionParser::SuggestResults::const_iterator i( 969 for (SearchSuggestionParser::SuggestResults::const_iterator i(
924 scored_results.begin()); i != scored_results.end(); ++i) { 970 scored_results.begin()); i != scored_results.end(); ++i) {
925 AddMatchToMap(*i, std::string(), did_not_accept_suggestion, true, map); 971 AddMatchToMap(*i, std::string(), did_not_accept_suggestion, true,
972 providers_.GetKeywordProviderURL() != NULL, map);
926 } 973 }
927 UMA_HISTOGRAM_TIMES("Omnibox.SearchProvider.AddHistoryResultsTime", 974 UMA_HISTOGRAM_TIMES("Omnibox.SearchProvider.AddHistoryResultsTime",
928 base::TimeTicks::Now() - start_time); 975 base::TimeTicks::Now() - start_time);
929 } 976 }
930 977
931 SearchSuggestionParser::SuggestResults SearchProvider::ScoreHistoryResults( 978 SearchSuggestionParser::SuggestResults SearchProvider::ScoreHistoryResults(
932 const HistoryResults& results, 979 const HistoryResults& results,
933 bool base_prevent_inline_autocomplete, 980 bool base_prevent_inline_autocomplete,
934 bool input_multiple_words, 981 bool input_multiple_words,
935 const base::string16& input_text, 982 const base::string16& input_text,
(...skipping 22 matching lines...) Expand all
958 prevent_search_history_inlining); 1005 prevent_search_history_inlining);
959 // Add the match to |scored_results| by putting the what-you-typed match 1006 // Add the match to |scored_results| by putting the what-you-typed match
960 // on the front and appending all other matches. We want the what-you- 1007 // on the front and appending all other matches. We want the what-you-
961 // typed match to always be first. 1008 // typed match to always be first.
962 SearchSuggestionParser::SuggestResults::iterator insertion_position = 1009 SearchSuggestionParser::SuggestResults::iterator insertion_position =
963 scored_results.end(); 1010 scored_results.end();
964 if (trimmed_suggestion == trimmed_input) { 1011 if (trimmed_suggestion == trimmed_input) {
965 found_what_you_typed_match = true; 1012 found_what_you_typed_match = true;
966 insertion_position = scored_results.begin(); 1013 insertion_position = scored_results.begin();
967 } 1014 }
968 scored_results.insert( 1015 SearchSuggestionParser::SuggestResult history_suggestion(
969 insertion_position, 1016 trimmed_suggestion, AutocompleteMatchType::SEARCH_HISTORY,
970 SearchSuggestionParser::SuggestResult( 1017 trimmed_suggestion, base::string16(), base::string16(),
971 trimmed_suggestion, AutocompleteMatchType::SEARCH_HISTORY, 1018 base::string16(), base::string16(), std::string(), std::string(),
972 trimmed_suggestion, base::string16(), base::string16(), 1019 is_keyword, relevance, false, false, trimmed_input);
973 base::string16(), base::string16(), std::string(), std::string(), 1020 // History results are synchronous; they are received at the last keystroke,
msw 2014/08/15 21:04:37 nit: s/upon/with/ remove ", not after it"
Mark P 2014/08/15 22:09:21 Did the latter. The former fails to apply. Ther
msw 2014/08/15 23:31:10 I meant to encourage "upon the last keystroke", bu
Mark P 2014/08/15 23:50:15 Switched to "upon".
974 is_keyword, relevance, false, false, trimmed_input)); 1021 // not after it.
1022 history_suggestion.set_received_after_last_keystroke(false);
1023 scored_results.insert(insertion_position, history_suggestion);
975 } 1024 }
976 1025
977 // History returns results sorted for us. However, we may have docked some 1026 // History returns results sorted for us. However, we may have docked some
978 // results' scores, so things are no longer in order. While keeping the 1027 // results' scores, so things are no longer in order. While keeping the
979 // what-you-typed match at the front (if it exists), do a stable sort to get 1028 // what-you-typed match at the front (if it exists), do a stable sort to get
980 // things back in order without otherwise disturbing results with equal 1029 // things back in order without otherwise disturbing results with equal
981 // scores, then force the scores to be unique, so that the order in which 1030 // scores, then force the scores to be unique, so that the order in which
982 // they're shown is deterministic. 1031 // they're shown is deterministic.
983 std::stable_sort(scored_results.begin() + 1032 std::stable_sort(scored_results.begin() +
984 (found_what_you_typed_match ? 1 : 0), 1033 (found_what_you_typed_match ? 1 : 0),
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
1037 last_relevance = i->relevance(); 1086 last_relevance = i->relevance();
1038 } 1087 }
1039 1088
1040 return scored_results; 1089 return scored_results;
1041 } 1090 }
1042 1091
1043 void SearchProvider::AddSuggestResultsToMap( 1092 void SearchProvider::AddSuggestResultsToMap(
1044 const SearchSuggestionParser::SuggestResults& results, 1093 const SearchSuggestionParser::SuggestResults& results,
1045 const std::string& metadata, 1094 const std::string& metadata,
1046 MatchMap* map) { 1095 MatchMap* map) {
1047 for (size_t i = 0; i < results.size(); ++i) 1096 for (size_t i = 0; i < results.size(); ++i) {
1048 AddMatchToMap(results[i], metadata, i, false, map); 1097 AddMatchToMap(results[i], metadata, i, false,
1098 providers_.GetKeywordProviderURL() != NULL, map);
1099 }
1049 } 1100 }
1050 1101
1051 int SearchProvider::GetVerbatimRelevance(bool* relevance_from_server) const { 1102 int SearchProvider::GetVerbatimRelevance(bool* relevance_from_server) const {
1052 // Use the suggested verbatim relevance score if it is non-negative (valid), 1103 // Use the suggested verbatim relevance score if it is non-negative (valid),
1053 // if inline autocomplete isn't prevented (always show verbatim on backspace), 1104 // if inline autocomplete isn't prevented (always show verbatim on backspace),
1054 // and if it won't suppress verbatim, leaving no default provider matches. 1105 // and if it won't suppress verbatim, leaving no default provider matches.
1055 // Otherwise, if the default provider returned no matches and was still able 1106 // Otherwise, if the default provider returned no matches and was still able
1056 // to suppress verbatim, the user would have no search/nav matches and may be 1107 // to suppress verbatim, the user would have no search/nav matches and may be
1057 // left unable to search using their default provider from the omnibox. 1108 // left unable to search using their default provider from the omnibox.
1058 // Check for results on each verbatim calculation, as results from older 1109 // Check for results on each verbatim calculation, as results from older
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
1197 if (inline_autocomplete_offset != base::string16::npos) 1248 if (inline_autocomplete_offset != base::string16::npos)
1198 ++inline_autocomplete_offset; 1249 ++inline_autocomplete_offset;
1199 } 1250 }
1200 if (inline_autocomplete_offset != base::string16::npos) { 1251 if (inline_autocomplete_offset != base::string16::npos) {
1201 DCHECK(inline_autocomplete_offset <= match.fill_into_edit.length()); 1252 DCHECK(inline_autocomplete_offset <= match.fill_into_edit.length());
1202 match.inline_autocompletion = 1253 match.inline_autocompletion =
1203 match.fill_into_edit.substr(inline_autocomplete_offset); 1254 match.fill_into_edit.substr(inline_autocomplete_offset);
1204 } 1255 }
1205 // An inlineable navsuggestion can only be the default match when there 1256 // An inlineable navsuggestion can only be the default match when there
1206 // is no keyword provider active, lest it appear first and break the user 1257 // is no keyword provider active, lest it appear first and break the user
1207 // out of keyword mode. It can also only be default if either the inline 1258 // out of keyword mode. We also must have received the navsuggestion before
1259 // the last keystroke. (We don't want asynchronous inline autocompletions.)
1260 // The navsuggestion can also only be default if either the inline
1208 // autocompletion is empty or we're not preventing inline autocompletion. 1261 // autocompletion is empty or we're not preventing inline autocompletion.
1209 // Finally, if we have an inlineable navsuggestion with an inline completion 1262 // Finally, if we have an inlineable navsuggestion with an inline completion
1210 // that we're not preventing, make sure we didn't trim any whitespace. 1263 // that we're not preventing, make sure we didn't trim any whitespace.
1211 // We don't want to claim http://foo.com/bar is inlineable against the 1264 // We don't want to claim http://foo.com/bar is inlineable against the
1212 // input "foo.com/b ". 1265 // input "foo.com/b ".
1213 match.allowed_to_be_default_match = (prefix != NULL) && 1266 match.allowed_to_be_default_match =
1267 (prefix != NULL) &&
1214 (providers_.GetKeywordProviderURL() == NULL) && 1268 (providers_.GetKeywordProviderURL() == NULL) &&
1269 !navigation.received_after_last_keystroke() &&
1215 (match.inline_autocompletion.empty() || 1270 (match.inline_autocompletion.empty() ||
1216 (!input_.prevent_inline_autocomplete() && !trimmed_whitespace)); 1271 (!input_.prevent_inline_autocomplete() && !trimmed_whitespace));
1217 match.EnsureUWYTIsAllowedToBeDefault( 1272 match.EnsureUWYTIsAllowedToBeDefault(
1218 input_.canonicalized_url(), providers_.template_url_service()); 1273 input_.canonicalized_url(), providers_.template_url_service());
1219 1274
1220 match.contents = navigation.match_contents(); 1275 match.contents = navigation.match_contents();
1221 match.contents_class = navigation.match_contents_class(); 1276 match.contents_class = navigation.match_contents_class();
1222 match.description = navigation.description(); 1277 match.description = navigation.description();
1223 AutocompleteMatch::ClassifyMatchInString(input, match.description, 1278 AutocompleteMatch::ClassifyMatchInString(input, match.description,
1224 ACMatchClassification::NONE, &match.description_class); 1279 ACMatchClassification::NONE, &match.description_class);
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
1277 last_answer_seen_.query_type = match->answer_type; 1332 last_answer_seen_.query_type = match->answer_type;
1278 } 1333 }
1279 1334
1280 void SearchProvider::DoAnswersQuery(const AutocompleteInput& input) { 1335 void SearchProvider::DoAnswersQuery(const AutocompleteInput& input) {
1281 // If the query text starts with trimmed input, this is valid prefetch data. 1336 // If the query text starts with trimmed input, this is valid prefetch data.
1282 prefetch_data_ = StartsWith(last_answer_seen_.full_query_text, 1337 prefetch_data_ = StartsWith(last_answer_seen_.full_query_text,
1283 base::CollapseWhitespace(input.text(), false), 1338 base::CollapseWhitespace(input.text(), false),
1284 false) ? 1339 false) ?
1285 last_answer_seen_ : AnswersQueryData(); 1340 last_answer_seen_ : AnswersQueryData();
1286 } 1341 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698