| 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::UpdateOldResults( | |
| 175 bool minimal_changes, | |
| 176 SearchSuggestionParser::Results* results) { | |
| 177 // When called without |minimal_changes|, it likely means the user has | |
| 178 // pressed a key. Revise the cached results appropriately. | |
| 179 if (!minimal_changes) { | |
| 180 for (SearchSuggestionParser::SuggestResults::iterator sug_it = | |
| 181 results->suggest_results.begin(); | |
| 182 sug_it != results->suggest_results.end(); ++sug_it) { | |
| 183 sug_it->set_received_after_last_keystroke(false); | |
| 184 } | |
| 185 for (SearchSuggestionParser::NavigationResults::iterator nav_it = | |
| 186 results->navigation_results.begin(); | |
| 187 nav_it != results->navigation_results.end(); ++nav_it) { | |
| 188 nav_it->set_received_after_last_keystroke(false); | |
| 189 } | |
| 190 } | |
| 191 } | |
| 192 | |
| 193 // static | |
| 194 ACMatches::iterator SearchProvider::FindTopMatch(ACMatches* matches) { | |
| 195 ACMatches::iterator it = matches->begin(); | |
| 196 while ((it != matches->end()) && !it->allowed_to_be_default_match) | |
| 197 ++it; | |
| 198 return it; | |
| 199 } | |
| 200 | |
| 201 void SearchProvider::Start(const AutocompleteInput& input, | 173 void SearchProvider::Start(const AutocompleteInput& input, |
| 202 bool minimal_changes) { | 174 bool minimal_changes) { |
| 203 // Do our best to load the model as early as possible. This will reduce | 175 // Do our best to load the model as early as possible. This will reduce |
| 204 // odds of having the model not ready when really needed (a non-empty input). | 176 // odds of having the model not ready when really needed (a non-empty input). |
| 205 TemplateURLService* model = providers_.template_url_service(); | 177 TemplateURLService* model = providers_.template_url_service(); |
| 206 DCHECK(model); | 178 DCHECK(model); |
| 207 model->Load(); | 179 model->Load(); |
| 208 | 180 |
| 209 matches_.clear(); | 181 matches_.clear(); |
| 210 field_trial_triggered_ = false; | 182 field_trial_triggered_ = false; |
| (...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 413 UMA_HISTOGRAM_TIMES("Omnibox.SuggestRequest.Success.GoogleResponseTime", | 385 UMA_HISTOGRAM_TIMES("Omnibox.SuggestRequest.Success.GoogleResponseTime", |
| 414 elapsed_time); | 386 elapsed_time); |
| 415 } else { | 387 } else { |
| 416 UMA_HISTOGRAM_TIMES("Omnibox.SuggestRequest.Failure.GoogleResponseTime", | 388 UMA_HISTOGRAM_TIMES("Omnibox.SuggestRequest.Failure.GoogleResponseTime", |
| 417 elapsed_time); | 389 elapsed_time); |
| 418 } | 390 } |
| 419 } | 391 } |
| 420 } | 392 } |
| 421 | 393 |
| 422 void SearchProvider::UpdateMatches() { | 394 void SearchProvider::UpdateMatches() { |
| 423 PersistTopSuggestions(&default_results_); | |
| 424 PersistTopSuggestions(&keyword_results_); | |
| 425 ConvertResultsToAutocompleteMatches(); | 395 ConvertResultsToAutocompleteMatches(); |
| 426 | 396 |
| 427 // Check constraints that may be violated by suggested relevances. | 397 // Check constraints that may be violated by suggested relevances. |
| 428 if (!matches_.empty() && | 398 if (!matches_.empty() && |
| 429 (default_results_.HasServerProvidedScores() || | 399 (default_results_.HasServerProvidedScores() || |
| 430 keyword_results_.HasServerProvidedScores())) { | 400 keyword_results_.HasServerProvidedScores())) { |
| 431 // These blocks attempt to repair undesirable behavior by suggested | 401 // These blocks attempt to repair undesirable behavior by suggested |
| 432 // relevances with minimal impact, preserving other suggested relevances. | 402 // relevances with minimal impact, preserving other suggested relevances. |
| 433 | 403 |
| 434 if ((providers_.GetKeywordProviderURL() != NULL) && | 404 if ((providers_.GetKeywordProviderURL() != NULL) && |
| 435 (FindTopMatch() == matches_.end())) { | 405 (FindTopMatch() == matches_.end())) { |
| 436 // In keyword mode, disregard the keyword verbatim suggested relevance | 406 // In keyword mode, disregard the keyword verbatim suggested relevance |
| 437 // if necessary, so at least one match is allowed to be default. (This | 407 // if necessary, so at least one match is allowed to be default. |
| 438 // is only necessary if we were told to suppress keyword verbatim and | 408 keyword_results_.verbatim_relevance = -1; |
| 439 // hence have no default keyword match.) Give keyword verbatim the | |
| 440 // lowest non-zero score to best reflect what the server desired. | |
| 441 DCHECK_EQ(0, keyword_results_.verbatim_relevance); | |
| 442 keyword_results_.verbatim_relevance = 1; | |
| 443 ConvertResultsToAutocompleteMatches(); | 409 ConvertResultsToAutocompleteMatches(); |
| 444 } | 410 } |
| 445 if (IsTopMatchSearchWithURLInput()) { | 411 if (IsTopMatchSearchWithURLInput()) { |
| 446 // Disregard the suggested search and verbatim relevances if the input | 412 // Disregard the suggested search and verbatim relevances if the input |
| 447 // type is URL and the top match is a highly-ranked search suggestion. | 413 // type is URL and the top match is a highly-ranked search suggestion. |
| 448 // For example, prevent a search for "foo.com" from outranking another | 414 // For example, prevent a search for "foo.com" from outranking another |
| 449 // provider's navigation for "foo.com" or "foo.com/url_from_history". | 415 // provider's navigation for "foo.com" or "foo.com/url_from_history". |
| 450 ApplyCalculatedSuggestRelevance(&keyword_results_.suggest_results); | 416 ApplyCalculatedSuggestRelevance(&keyword_results_.suggest_results); |
| 451 ApplyCalculatedSuggestRelevance(&default_results_.suggest_results); | 417 ApplyCalculatedSuggestRelevance(&default_results_.suggest_results); |
| 452 default_results_.verbatim_relevance = -1; | 418 default_results_.verbatim_relevance = -1; |
| 453 keyword_results_.verbatim_relevance = -1; | 419 keyword_results_.verbatim_relevance = -1; |
| 454 ConvertResultsToAutocompleteMatches(); | 420 ConvertResultsToAutocompleteMatches(); |
| 455 } | 421 } |
| 456 if (FindTopMatch() == matches_.end()) { | 422 if (FindTopMatch() == matches_.end()) { |
| 457 // Guarantee that SearchProvider returns a legal default match. (The | 423 // Guarantee that SearchProvider returns a legal default match. (The |
| 458 // omnibox always needs at least one legal default match, and it relies | 424 // omnibox always needs at least one legal default match, and it relies |
| 459 // on SearchProvider to always return one.) Give the verbatim suggestion | 425 // on SearchProvider to always return one.) |
| 460 // the lowest non-zero scores to best reflect what the server desired. | 426 ApplyCalculatedRelevance(); |
| 461 DCHECK_EQ(0, default_results_.verbatim_relevance); | |
| 462 default_results_.verbatim_relevance = 1; | |
| 463 // We do not have to alter keyword_results_.verbatim_relevance here. | |
| 464 // If the user is in keyword mode, we already reverted (earlier in this | |
| 465 // function) the instructions to suppress keyword verbatim. | |
| 466 ConvertResultsToAutocompleteMatches(); | 427 ConvertResultsToAutocompleteMatches(); |
| 467 } | 428 } |
| 468 DCHECK(!IsTopMatchSearchWithURLInput()); | 429 DCHECK(!IsTopMatchSearchWithURLInput()); |
| 469 DCHECK(FindTopMatch() != matches_.end()); | 430 DCHECK(FindTopMatch() != matches_.end()); |
| 470 } | 431 } |
| 471 UMA_HISTOGRAM_CUSTOM_COUNTS( | 432 UMA_HISTOGRAM_CUSTOM_COUNTS( |
| 472 "Omnibox.SearchProviderMatches", matches_.size(), 1, 6, 7); | 433 "Omnibox.SearchProviderMatches", matches_.size(), 1, 6, 7); |
| 473 | |
| 474 // Record the top suggestion (if any) for future use. | |
| 475 top_query_suggestion_match_contents_ = base::string16(); | |
| 476 top_navigation_suggestion_ = GURL(); | |
| 477 ACMatches::const_iterator first_match = FindTopMatch(); | |
| 478 if ((first_match != matches_.end()) && | |
| 479 !first_match->inline_autocompletion.empty()) { | |
| 480 // Identify if this match came from a query suggestion or a navsuggestion. | |
| 481 // In either case, extracts the identifying feature of the suggestion | |
| 482 // (query string or navigation url). | |
| 483 if (AutocompleteMatch::IsSearchType(first_match->type)) | |
| 484 top_query_suggestion_match_contents_ = first_match->contents; | |
| 485 else | |
| 486 top_navigation_suggestion_ = first_match->destination_url; | |
| 487 } | |
| 488 | |
| 489 UpdateDone(); | 434 UpdateDone(); |
| 490 } | 435 } |
| 491 | 436 |
| 492 void SearchProvider::Run() { | 437 void SearchProvider::Run() { |
| 493 // Start a new request with the current input. | 438 // Start a new request with the current input. |
| 494 suggest_results_pending_ = 0; | 439 suggest_results_pending_ = 0; |
| 495 time_suggest_request_sent_ = base::TimeTicks::Now(); | 440 time_suggest_request_sent_ = base::TimeTicks::Now(); |
| 496 | 441 |
| 497 default_fetcher_.reset(CreateSuggestFetcher(kDefaultProviderURLFetcherID, | 442 default_fetcher_.reset(CreateSuggestFetcher(kDefaultProviderURLFetcherID, |
| 498 providers_.GetDefaultProviderURL(), input_)); | 443 providers_.GetDefaultProviderURL(), input_)); |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 569 (!default_results_.suggest_results.empty() || | 514 (!default_results_.suggest_results.empty() || |
| 570 !default_results_.navigation_results.empty() || | 515 !default_results_.navigation_results.empty() || |
| 571 !keyword_results_.suggest_results.empty() || | 516 !keyword_results_.suggest_results.empty() || |
| 572 !keyword_results_.navigation_results.empty() || | 517 !keyword_results_.navigation_results.empty() || |
| 573 (!done_ && input_.want_asynchronous_matches()))) | 518 (!done_ && input_.want_asynchronous_matches()))) |
| 574 return; | 519 return; |
| 575 | 520 |
| 576 // We can't keep running any previous query, so halt it. | 521 // We can't keep running any previous query, so halt it. |
| 577 StopSuggest(); | 522 StopSuggest(); |
| 578 | 523 |
| 579 UpdateAllOldResults(minimal_changes); | 524 // Remove existing results that cannot inline autocomplete the new input. |
| 525 RemoveAllStaleResults(); |
| 580 | 526 |
| 581 // Update the content classifications of remaining results so they look good | 527 // Update the content classifications of remaining results so they look good |
| 582 // against the current input. | 528 // against the current input. |
| 583 UpdateMatchContentsClass(input_.text(), &default_results_); | 529 UpdateMatchContentsClass(input_.text(), &default_results_); |
| 584 if (!keyword_input_.text().empty()) | 530 if (!keyword_input_.text().empty()) |
| 585 UpdateMatchContentsClass(keyword_input_.text(), &keyword_results_); | 531 UpdateMatchContentsClass(keyword_input_.text(), &keyword_results_); |
| 586 | 532 |
| 587 // We can't start a new query if we're only allowed synchronous results. | 533 // We can't start a new query if we're only allowed synchronous results. |
| 588 if (!input_.want_asynchronous_matches()) | 534 if (!input_.want_asynchronous_matches()) |
| 589 return; | 535 return; |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 653 // Don't send anything for https except the hostname. Hostnames are OK | 599 // Don't send anything for https except the hostname. Hostnames are OK |
| 654 // because they are visible when the TCP connection is established, but the | 600 // because they are visible when the TCP connection is established, but the |
| 655 // specific path may reveal private information. | 601 // specific path may reveal private information. |
| 656 if (LowerCaseEqualsASCII(input_.scheme(), url::kHttpsScheme) && | 602 if (LowerCaseEqualsASCII(input_.scheme(), url::kHttpsScheme) && |
| 657 parts.path.is_nonempty()) | 603 parts.path.is_nonempty()) |
| 658 return false; | 604 return false; |
| 659 | 605 |
| 660 return true; | 606 return true; |
| 661 } | 607 } |
| 662 | 608 |
| 663 void SearchProvider::UpdateAllOldResults(bool minimal_changes) { | 609 void SearchProvider::RemoveAllStaleResults() { |
| 664 if (keyword_input_.text().empty()) { | 610 if (keyword_input_.text().empty()) { |
| 665 // User is either in keyword mode with a blank input or out of | 611 // User is either in keyword mode with a blank input or out of |
| 666 // keyword mode entirely. | 612 // keyword mode entirely. |
| 667 keyword_results_.Clear(); | 613 keyword_results_.Clear(); |
| 668 } | 614 } |
| 669 UpdateOldResults(minimal_changes, &default_results_); | |
| 670 UpdateOldResults(minimal_changes, &keyword_results_); | |
| 671 } | 615 } |
| 672 | 616 |
| 673 void SearchProvider::PersistTopSuggestions( | 617 void SearchProvider::ApplyCalculatedRelevance() { |
| 674 SearchSuggestionParser::Results* results) { | 618 ApplyCalculatedSuggestRelevance(&keyword_results_.suggest_results); |
| 675 // Mark any results matching the current top results as having been received | 619 ApplyCalculatedSuggestRelevance(&default_results_.suggest_results); |
| 676 // prior to the last keystroke. That prevents asynchronous updates from | 620 ApplyCalculatedNavigationRelevance(&keyword_results_.navigation_results); |
| 677 // clobbering top results, which may be used for inline autocompletion. | 621 ApplyCalculatedNavigationRelevance(&default_results_.navigation_results); |
| 678 // Other results don't need similar changes, because they shouldn't be | 622 default_results_.verbatim_relevance = -1; |
| 679 // displayed asynchronously anyway. | 623 keyword_results_.verbatim_relevance = -1; |
| 680 if (!top_query_suggestion_match_contents_.empty()) { | |
| 681 for (SearchSuggestionParser::SuggestResults::iterator sug_it = | |
| 682 results->suggest_results.begin(); | |
| 683 sug_it != results->suggest_results.end(); ++sug_it) { | |
| 684 if (sug_it->match_contents() == top_query_suggestion_match_contents_) | |
| 685 sug_it->set_received_after_last_keystroke(false); | |
| 686 } | |
| 687 } | |
| 688 if (top_navigation_suggestion_.is_valid()) { | |
| 689 for (SearchSuggestionParser::NavigationResults::iterator nav_it = | |
| 690 results->navigation_results.begin(); | |
| 691 nav_it != results->navigation_results.end(); ++nav_it) { | |
| 692 if (nav_it->url() == top_navigation_suggestion_) | |
| 693 nav_it->set_received_after_last_keystroke(false); | |
| 694 } | |
| 695 } | |
| 696 } | 624 } |
| 697 | 625 |
| 698 void SearchProvider::ApplyCalculatedSuggestRelevance( | 626 void SearchProvider::ApplyCalculatedSuggestRelevance( |
| 699 SearchSuggestionParser::SuggestResults* list) { | 627 SearchSuggestionParser::SuggestResults* list) { |
| 700 for (size_t i = 0; i < list->size(); ++i) { | 628 for (size_t i = 0; i < list->size(); ++i) { |
| 701 SearchSuggestionParser::SuggestResult& result = (*list)[i]; | 629 SearchSuggestionParser::SuggestResult& result = (*list)[i]; |
| 702 result.set_relevance( | 630 result.set_relevance( |
| 703 result.CalculateRelevance(input_, providers_.has_keyword_provider()) + | 631 result.CalculateRelevance(input_, providers_.has_keyword_provider()) + |
| 704 (list->size() - i - 1)); | 632 (list->size() - i - 1)); |
| 705 result.set_relevance_from_server(false); | 633 result.set_relevance_from_server(false); |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 854 default_results_.metadata, &map); | 782 default_results_.metadata, &map); |
| 855 | 783 |
| 856 ACMatches matches; | 784 ACMatches matches; |
| 857 for (MatchMap::const_iterator i(map.begin()); i != map.end(); ++i) | 785 for (MatchMap::const_iterator i(map.begin()); i != map.end(); ++i) |
| 858 matches.push_back(i->second); | 786 matches.push_back(i->second); |
| 859 | 787 |
| 860 AddNavigationResultsToMatches(keyword_results_.navigation_results, &matches); | 788 AddNavigationResultsToMatches(keyword_results_.navigation_results, &matches); |
| 861 AddNavigationResultsToMatches(default_results_.navigation_results, &matches); | 789 AddNavigationResultsToMatches(default_results_.navigation_results, &matches); |
| 862 | 790 |
| 863 // Now add the most relevant matches to |matches_|. We take up to kMaxMatches | 791 // Now add the most relevant matches to |matches_|. We take up to kMaxMatches |
| 864 // suggest/navsuggest matches, regardless of origin. We always include in | 792 // suggest/navsuggest matches, regardless of origin. If Instant Extended is |
| 865 // that set a legal default match if possible. If Instant Extended is enabled | 793 // enabled and we have server-provided (and thus hopefully more accurate) |
| 866 // and we have server-provided (and thus hopefully more accurate) scores for | 794 // scores for some suggestions, we allow more of those, until we reach |
| 867 // some suggestions, we allow more of those, until we reach | |
| 868 // AutocompleteResult::kMaxMatches total matches (that is, enough to fill the | 795 // AutocompleteResult::kMaxMatches total matches (that is, enough to fill the |
| 869 // whole popup). | 796 // whole popup). |
| 870 // | 797 // |
| 871 // We will always return any verbatim matches, no matter how we obtained their | 798 // We will always return any verbatim matches, no matter how we obtained their |
| 872 // scores, unless we have already accepted AutocompleteResult::kMaxMatches | 799 // scores, unless we have already accepted AutocompleteResult::kMaxMatches |
| 873 // higher-scoring matches under the conditions above. | 800 // higher-scoring matches under the conditions above. |
| 874 std::sort(matches.begin(), matches.end(), &AutocompleteMatch::MoreRelevant); | 801 std::sort(matches.begin(), matches.end(), &AutocompleteMatch::MoreRelevant); |
| 875 matches_.clear(); | 802 matches_.clear(); |
| 876 // Guarantee that if there's a legal default match anywhere in the result | |
| 877 // set that it'll get returned. The rotate() call does this by moving the | |
| 878 // default match to the front of the list. | |
| 879 ACMatches::iterator default_match = FindTopMatch(&matches); | |
| 880 if (default_match != matches.end()) | |
| 881 std::rotate(matches.begin(), default_match, default_match + 1); | |
| 882 | 803 |
| 883 size_t num_suggestions = 0; | 804 size_t num_suggestions = 0; |
| 884 for (ACMatches::const_iterator i(matches.begin()); | 805 for (ACMatches::const_iterator i(matches.begin()); |
| 885 (i != matches.end()) && | 806 (i != matches.end()) && |
| 886 (matches_.size() < AutocompleteResult::kMaxMatches); | 807 (matches_.size() < AutocompleteResult::kMaxMatches); |
| 887 ++i) { | 808 ++i) { |
| 888 // SEARCH_OTHER_ENGINE is only used in the SearchProvider for the keyword | 809 // SEARCH_OTHER_ENGINE is only used in the SearchProvider for the keyword |
| 889 // verbatim result, so this condition basically means "if this match is a | 810 // verbatim result, so this condition basically means "if this match is a |
| 890 // suggestion of some sort". | 811 // suggestion of some sort". |
| 891 if ((i->type != AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED) && | 812 if ((i->type != AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED) && |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1010 prevent_search_history_inlining); | 931 prevent_search_history_inlining); |
| 1011 // Add the match to |scored_results| by putting the what-you-typed match | 932 // Add the match to |scored_results| by putting the what-you-typed match |
| 1012 // on the front and appending all other matches. We want the what-you- | 933 // on the front and appending all other matches. We want the what-you- |
| 1013 // typed match to always be first. | 934 // typed match to always be first. |
| 1014 SearchSuggestionParser::SuggestResults::iterator insertion_position = | 935 SearchSuggestionParser::SuggestResults::iterator insertion_position = |
| 1015 scored_results.end(); | 936 scored_results.end(); |
| 1016 if (trimmed_suggestion == trimmed_input) { | 937 if (trimmed_suggestion == trimmed_input) { |
| 1017 found_what_you_typed_match = true; | 938 found_what_you_typed_match = true; |
| 1018 insertion_position = scored_results.begin(); | 939 insertion_position = scored_results.begin(); |
| 1019 } | 940 } |
| 1020 SearchSuggestionParser::SuggestResult history_suggestion( | 941 scored_results.insert( |
| 1021 trimmed_suggestion, AutocompleteMatchType::SEARCH_HISTORY, | 942 insertion_position, |
| 1022 trimmed_suggestion, base::string16(), base::string16(), | 943 SearchSuggestionParser::SuggestResult( |
| 1023 base::string16(), base::string16(), std::string(), std::string(), | 944 trimmed_suggestion, AutocompleteMatchType::SEARCH_HISTORY, |
| 1024 is_keyword, relevance, false, false, trimmed_input); | 945 trimmed_suggestion, base::string16(), base::string16(), |
| 1025 // History results are synchronous; they are received upon the last | 946 base::string16(), base::string16(), std::string(), std::string(), |
| 1026 // keystroke. | 947 is_keyword, relevance, false, false, trimmed_input)); |
| 1027 history_suggestion.set_received_after_last_keystroke(false); | |
| 1028 scored_results.insert(insertion_position, history_suggestion); | |
| 1029 } | 948 } |
| 1030 | 949 |
| 1031 // History returns results sorted for us. However, we may have docked some | 950 // History returns results sorted for us. However, we may have docked some |
| 1032 // results' scores, so things are no longer in order. While keeping the | 951 // results' scores, so things are no longer in order. While keeping the |
| 1033 // what-you-typed match at the front (if it exists), do a stable sort to get | 952 // what-you-typed match at the front (if it exists), do a stable sort to get |
| 1034 // things back in order without otherwise disturbing results with equal | 953 // things back in order without otherwise disturbing results with equal |
| 1035 // scores, then force the scores to be unique, so that the order in which | 954 // scores, then force the scores to be unique, so that the order in which |
| 1036 // they're shown is deterministic. | 955 // they're shown is deterministic. |
| 1037 std::stable_sort(scored_results.begin() + | 956 std::stable_sort(scored_results.begin() + |
| 1038 (found_what_you_typed_match ? 1 : 0), | 957 (found_what_you_typed_match ? 1 : 0), |
| (...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1253 if (inline_autocomplete_offset != base::string16::npos) | 1172 if (inline_autocomplete_offset != base::string16::npos) |
| 1254 ++inline_autocomplete_offset; | 1173 ++inline_autocomplete_offset; |
| 1255 } | 1174 } |
| 1256 if (inline_autocomplete_offset != base::string16::npos) { | 1175 if (inline_autocomplete_offset != base::string16::npos) { |
| 1257 DCHECK(inline_autocomplete_offset <= match.fill_into_edit.length()); | 1176 DCHECK(inline_autocomplete_offset <= match.fill_into_edit.length()); |
| 1258 match.inline_autocompletion = | 1177 match.inline_autocompletion = |
| 1259 match.fill_into_edit.substr(inline_autocomplete_offset); | 1178 match.fill_into_edit.substr(inline_autocomplete_offset); |
| 1260 } | 1179 } |
| 1261 // An inlineable navsuggestion can only be the default match when there | 1180 // An inlineable navsuggestion can only be the default match when there |
| 1262 // is no keyword provider active, lest it appear first and break the user | 1181 // is no keyword provider active, lest it appear first and break the user |
| 1263 // out of keyword mode. We also must have received the navsuggestion before | 1182 // out of keyword mode. It can also only be default if either the inline |
| 1264 // the last keystroke, to prevent asynchronous inline autocompletions changes. | |
| 1265 // The navsuggestion can also only be default if either the inline | |
| 1266 // autocompletion is empty or we're not preventing inline autocompletion. | 1183 // autocompletion is empty or we're not preventing inline autocompletion. |
| 1267 // Finally, if we have an inlineable navsuggestion with an inline completion | 1184 // Finally, if we have an inlineable navsuggestion with an inline completion |
| 1268 // that we're not preventing, make sure we didn't trim any whitespace. | 1185 // that we're not preventing, make sure we didn't trim any whitespace. |
| 1269 // We don't want to claim http://foo.com/bar is inlineable against the | 1186 // We don't want to claim http://foo.com/bar is inlineable against the |
| 1270 // input "foo.com/b ". | 1187 // input "foo.com/b ". |
| 1271 match.allowed_to_be_default_match = | 1188 match.allowed_to_be_default_match = (prefix != NULL) && |
| 1272 (prefix != NULL) && | |
| 1273 (providers_.GetKeywordProviderURL() == NULL) && | 1189 (providers_.GetKeywordProviderURL() == NULL) && |
| 1274 !navigation.received_after_last_keystroke() && | |
| 1275 (match.inline_autocompletion.empty() || | 1190 (match.inline_autocompletion.empty() || |
| 1276 (!input_.prevent_inline_autocomplete() && !trimmed_whitespace)); | 1191 (!input_.prevent_inline_autocomplete() && !trimmed_whitespace)); |
| 1277 match.EnsureUWYTIsAllowedToBeDefault( | 1192 match.EnsureUWYTIsAllowedToBeDefault( |
| 1278 input_.canonicalized_url(), providers_.template_url_service()); | 1193 input_.canonicalized_url(), providers_.template_url_service()); |
| 1279 | 1194 |
| 1280 match.contents = navigation.match_contents(); | 1195 match.contents = navigation.match_contents(); |
| 1281 match.contents_class = navigation.match_contents_class(); | 1196 match.contents_class = navigation.match_contents_class(); |
| 1282 match.description = navigation.description(); | 1197 match.description = navigation.description(); |
| 1283 AutocompleteMatch::ClassifyMatchInString(input, match.description, | 1198 AutocompleteMatch::ClassifyMatchInString(input, match.description, |
| 1284 ACMatchClassification::NONE, &match.description_class); | 1199 ACMatchClassification::NONE, &match.description_class); |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1337 last_answer_seen_.query_type = match->answer_type; | 1252 last_answer_seen_.query_type = match->answer_type; |
| 1338 } | 1253 } |
| 1339 | 1254 |
| 1340 void SearchProvider::DoAnswersQuery(const AutocompleteInput& input) { | 1255 void SearchProvider::DoAnswersQuery(const AutocompleteInput& input) { |
| 1341 // If the query text starts with trimmed input, this is valid prefetch data. | 1256 // If the query text starts with trimmed input, this is valid prefetch data. |
| 1342 prefetch_data_ = StartsWith(last_answer_seen_.full_query_text, | 1257 prefetch_data_ = StartsWith(last_answer_seen_.full_query_text, |
| 1343 base::CollapseWhitespace(input.text(), false), | 1258 base::CollapseWhitespace(input.text(), false), |
| 1344 false) ? | 1259 false) ? |
| 1345 last_answer_seen_ : AnswersQueryData(); | 1260 last_answer_seen_ : AnswersQueryData(); |
| 1346 } | 1261 } |
| OLD | NEW |