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