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