Chromium Code Reviews| 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 |