OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 } |
OLD | NEW |