| 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" |
| 11 #include "base/callback.h" | 11 #include "base/callback.h" |
| 12 #include "base/command_line.h" | |
| 13 #include "base/i18n/break_iterator.h" | 12 #include "base/i18n/break_iterator.h" |
| 14 #include "base/i18n/case_conversion.h" | 13 #include "base/i18n/case_conversion.h" |
| 15 #include "base/json/json_string_value_serializer.h" | 14 #include "base/json/json_string_value_serializer.h" |
| 16 #include "base/message_loop/message_loop.h" | |
| 17 #include "base/metrics/histogram.h" | 15 #include "base/metrics/histogram.h" |
| 18 #include "base/metrics/user_metrics.h" | 16 #include "base/metrics/user_metrics.h" |
| 19 #include "base/prefs/pref_service.h" | |
| 20 #include "base/rand_util.h" | 17 #include "base/rand_util.h" |
| 21 #include "base/strings/string_util.h" | 18 #include "base/strings/string_util.h" |
| 22 #include "base/strings/utf_string_conversions.h" | 19 #include "base/strings/utf_string_conversions.h" |
| 23 #include "chrome/browser/autocomplete/autocomplete_classifier.h" | |
| 24 #include "chrome/browser/autocomplete/autocomplete_classifier_factory.h" | |
| 25 #include "chrome/browser/autocomplete/chrome_autocomplete_scheme_classifier.h" | |
| 26 #include "chrome/browser/history/history_service.h" | |
| 27 #include "chrome/browser/history/history_service_factory.h" | |
| 28 #include "chrome/browser/profiles/profile.h" | |
| 29 #include "chrome/common/pref_names.h" | |
| 30 #include "components/google/core/browser/google_util.h" | |
| 31 #include "components/history/core/browser/in_memory_database.h" | 20 #include "components/history/core/browser/in_memory_database.h" |
| 32 #include "components/history/core/browser/keyword_search_term.h" | 21 #include "components/history/core/browser/keyword_search_term.h" |
| 33 #include "components/metrics/proto/omnibox_input_type.pb.h" | 22 #include "components/metrics/proto/omnibox_input_type.pb.h" |
| 23 #include "components/omnibox/autocomplete_provider_delegate.h" |
| 34 #include "components/omnibox/autocomplete_provider_listener.h" | 24 #include "components/omnibox/autocomplete_provider_listener.h" |
| 35 #include "components/omnibox/autocomplete_result.h" | 25 #include "components/omnibox/autocomplete_result.h" |
| 36 #include "components/omnibox/keyword_provider.h" | 26 #include "components/omnibox/keyword_provider.h" |
| 37 #include "components/omnibox/omnibox_field_trial.h" | 27 #include "components/omnibox/omnibox_field_trial.h" |
| 38 #include "components/omnibox/url_prefix.h" | 28 #include "components/omnibox/url_prefix.h" |
| 39 #include "components/search/search.h" | 29 #include "components/search/search.h" |
| 40 #include "components/search_engines/template_url_prepopulate_data.h" | 30 #include "components/search_engines/template_url_prepopulate_data.h" |
| 41 #include "components/search_engines/template_url_service.h" | 31 #include "components/search_engines/template_url_service.h" |
| 42 #include "components/variations/variations_http_header_provider.h" | 32 #include "components/variations/variations_http_header_provider.h" |
| 43 #include "grit/components_strings.h" | 33 #include "grit/components_strings.h" |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 122 return a.relevance() > b.relevance(); | 112 return a.relevance() > b.relevance(); |
| 123 } | 113 } |
| 124 }; | 114 }; |
| 125 | 115 |
| 126 | 116 |
| 127 // SearchProvider ------------------------------------------------------------- | 117 // SearchProvider ------------------------------------------------------------- |
| 128 | 118 |
| 129 // static | 119 // static |
| 130 int SearchProvider::kMinimumTimeBetweenSuggestQueriesMs = 100; | 120 int SearchProvider::kMinimumTimeBetweenSuggestQueriesMs = 100; |
| 131 | 121 |
| 132 SearchProvider::SearchProvider(AutocompleteProviderListener* listener, | 122 SearchProvider::SearchProvider( |
| 133 TemplateURLService* template_url_service, | 123 AutocompleteProviderListener* listener, |
| 134 Profile* profile) | 124 TemplateURLService* template_url_service, |
| 135 : BaseSearchProvider(template_url_service, profile, | 125 scoped_ptr<AutocompleteProviderDelegate> delegate) |
| 126 : BaseSearchProvider(template_url_service, delegate.Pass(), |
| 136 AutocompleteProvider::TYPE_SEARCH), | 127 AutocompleteProvider::TYPE_SEARCH), |
| 137 listener_(listener), | 128 listener_(listener), |
| 138 suggest_results_pending_(0), | 129 suggest_results_pending_(0), |
| 139 providers_(template_url_service), | 130 providers_(template_url_service), |
| 140 answers_cache_(1) { | 131 answers_cache_(1) { |
| 141 } | 132 } |
| 142 | 133 |
| 143 // static | 134 // static |
| 144 std::string SearchProvider::GetSuggestMetadata(const AutocompleteMatch& match) { | 135 std::string SearchProvider::GetSuggestMetadata(const AutocompleteMatch& match) { |
| 145 return match.GetAdditionalInfo(kSuggestMetadataKey); | 136 return match.GetAdditionalInfo(kSuggestMetadataKey); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 175 bool minimal_changes) { | 166 bool minimal_changes) { |
| 176 // Do our best to load the model as early as possible. This will reduce | 167 // Do our best to load the model as early as possible. This will reduce |
| 177 // odds of having the model not ready when really needed (a non-empty input). | 168 // odds of having the model not ready when really needed (a non-empty input). |
| 178 TemplateURLService* model = providers_.template_url_service(); | 169 TemplateURLService* model = providers_.template_url_service(); |
| 179 DCHECK(model); | 170 DCHECK(model); |
| 180 model->Load(); | 171 model->Load(); |
| 181 | 172 |
| 182 matches_.clear(); | 173 matches_.clear(); |
| 183 field_trial_triggered_ = false; | 174 field_trial_triggered_ = false; |
| 184 | 175 |
| 185 // Can't return search/suggest results for bogus input or without a profile. | 176 // Can't return search/suggest results for bogus input. |
| 186 if (!profile_ || (input.type() == metrics::OmniboxInputType::INVALID)) { | 177 if (input.type() == metrics::OmniboxInputType::INVALID) { |
| 187 Stop(true); | 178 Stop(true); |
| 188 return; | 179 return; |
| 189 } | 180 } |
| 190 | 181 |
| 191 keyword_input_ = input; | 182 keyword_input_ = input; |
| 192 const TemplateURL* keyword_provider = | 183 const TemplateURL* keyword_provider = |
| 193 KeywordProvider::GetSubstitutingTemplateURLForInput(model, | 184 KeywordProvider::GetSubstitutingTemplateURLForInput(model, |
| 194 &keyword_input_); | 185 &keyword_input_); |
| 195 if (keyword_provider == NULL) | 186 if (keyword_provider == NULL) |
| 196 keyword_input_.Clear(); | 187 keyword_input_.Clear(); |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 334 } | 325 } |
| 335 | 326 |
| 336 void SearchProvider::UpdateMatchContentsClass( | 327 void SearchProvider::UpdateMatchContentsClass( |
| 337 const base::string16& input_text, | 328 const base::string16& input_text, |
| 338 SearchSuggestionParser::Results* results) { | 329 SearchSuggestionParser::Results* results) { |
| 339 for (SearchSuggestionParser::SuggestResults::iterator sug_it = | 330 for (SearchSuggestionParser::SuggestResults::iterator sug_it = |
| 340 results->suggest_results.begin(); | 331 results->suggest_results.begin(); |
| 341 sug_it != results->suggest_results.end(); ++sug_it) { | 332 sug_it != results->suggest_results.end(); ++sug_it) { |
| 342 sug_it->ClassifyMatchContents(false, input_text); | 333 sug_it->ClassifyMatchContents(false, input_text); |
| 343 } | 334 } |
| 344 const std::string languages( | 335 const std::string languages(delegate_->GetAcceptLanguages()); |
| 345 profile_->GetPrefs()->GetString(prefs::kAcceptLanguages)); | |
| 346 for (SearchSuggestionParser::NavigationResults::iterator nav_it = | 336 for (SearchSuggestionParser::NavigationResults::iterator nav_it = |
| 347 results->navigation_results.begin(); | 337 results->navigation_results.begin(); |
| 348 nav_it != results->navigation_results.end(); ++nav_it) { | 338 nav_it != results->navigation_results.end(); ++nav_it) { |
| 349 nav_it->CalculateAndClassifyMatchContents(false, input_text, languages); | 339 nav_it->CalculateAndClassifyMatchContents(false, input_text, languages); |
| 350 } | 340 } |
| 351 } | 341 } |
| 352 | 342 |
| 353 void SearchProvider::SortResults(bool is_keyword, | 343 void SearchProvider::SortResults(bool is_keyword, |
| 354 SearchSuggestionParser::Results* results) { | 344 SearchSuggestionParser::Results* results) { |
| 355 // Ignore suggested scores for non-keyword matches in keyword mode; if the | 345 // Ignore suggested scores for non-keyword matches in keyword mode; if the |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 476 if (minimal_changes) | 466 if (minimal_changes) |
| 477 return; | 467 return; |
| 478 | 468 |
| 479 keyword_history_results_.clear(); | 469 keyword_history_results_.clear(); |
| 480 default_history_results_.clear(); | 470 default_history_results_.clear(); |
| 481 | 471 |
| 482 if (OmniboxFieldTrial::SearchHistoryDisable( | 472 if (OmniboxFieldTrial::SearchHistoryDisable( |
| 483 input_.current_page_classification())) | 473 input_.current_page_classification())) |
| 484 return; | 474 return; |
| 485 | 475 |
| 486 HistoryService* const history_service = | 476 history::URLDatabase* url_db = delegate_->InMemoryDatabase(); |
| 487 HistoryServiceFactory::GetForProfile(profile_, Profile::EXPLICIT_ACCESS); | |
| 488 history::URLDatabase* url_db = history_service ? | |
| 489 history_service->InMemoryDatabase() : NULL; | |
| 490 if (!url_db) | 477 if (!url_db) |
| 491 return; | 478 return; |
| 492 | 479 |
| 493 // Request history for both the keyword and default provider. We grab many | 480 // Request history for both the keyword and default provider. We grab many |
| 494 // more matches than we'll ultimately clamp to so that if there are several | 481 // more matches than we'll ultimately clamp to so that if there are several |
| 495 // recent multi-word matches who scores are lowered (see | 482 // recent multi-word matches who scores are lowered (see |
| 496 // AddHistoryResultsToMap()), they won't crowd out older, higher-scoring | 483 // AddHistoryResultsToMap()), they won't crowd out older, higher-scoring |
| 497 // matches. Note that this doesn't fix the problem entirely, but merely | 484 // matches. Note that this doesn't fix the problem entirely, but merely |
| 498 // limits it to cases with a very large number of such multi-word matches; for | 485 // limits it to cases with a very large number of such multi-word matches; for |
| 499 // now, this seems OK compared with the complexity of a real fix, which would | 486 // now, this seems OK compared with the complexity of a real fix, which would |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 560 return; | 547 return; |
| 561 } | 548 } |
| 562 timer_.Start(FROM_HERE, next_suggest_time - now, this, &SearchProvider::Run); | 549 timer_.Start(FROM_HERE, next_suggest_time - now, this, &SearchProvider::Run); |
| 563 } | 550 } |
| 564 | 551 |
| 565 bool SearchProvider::IsQuerySuitableForSuggest() const { | 552 bool SearchProvider::IsQuerySuitableForSuggest() const { |
| 566 // Don't run Suggest in incognito mode, if the engine doesn't support it, or | 553 // Don't run Suggest in incognito mode, if the engine doesn't support it, or |
| 567 // if the user has disabled it. | 554 // if the user has disabled it. |
| 568 const TemplateURL* default_url = providers_.GetDefaultProviderURL(); | 555 const TemplateURL* default_url = providers_.GetDefaultProviderURL(); |
| 569 const TemplateURL* keyword_url = providers_.GetKeywordProviderURL(); | 556 const TemplateURL* keyword_url = providers_.GetKeywordProviderURL(); |
| 570 if (profile_->IsOffTheRecord() || | 557 if (delegate_->IsOffTheRecord() || |
| 571 ((!default_url || default_url->suggestions_url().empty()) && | 558 ((!default_url || default_url->suggestions_url().empty()) && |
| 572 (!keyword_url || keyword_url->suggestions_url().empty())) || | 559 (!keyword_url || keyword_url->suggestions_url().empty())) || |
| 573 !profile_->GetPrefs()->GetBoolean(prefs::kSearchSuggestEnabled)) | 560 !delegate_->SearchSuggestEnabled()) |
| 574 return false; | 561 return false; |
| 575 | 562 |
| 576 // If the input type might be a URL, we take extra care so that private data | 563 // If the input type might be a URL, we take extra care so that private data |
| 577 // isn't sent to the server. | 564 // isn't sent to the server. |
| 578 | 565 |
| 579 // FORCED_QUERY means the user is explicitly asking us to search for this, so | 566 // FORCED_QUERY means the user is explicitly asking us to search for this, so |
| 580 // we assume it isn't a URL and/or there isn't private data. | 567 // we assume it isn't a URL and/or there isn't private data. |
| 581 if (input_.type() == metrics::OmniboxInputType::FORCED_QUERY) | 568 if (input_.type() == metrics::OmniboxInputType::FORCED_QUERY) |
| 582 return true; | 569 return true; |
| 583 | 570 |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 684 } | 671 } |
| 685 GURL suggest_url(template_url->suggestions_url_ref().ReplaceSearchTerms( | 672 GURL suggest_url(template_url->suggestions_url_ref().ReplaceSearchTerms( |
| 686 search_term_args, | 673 search_term_args, |
| 687 providers_.template_url_service()->search_terms_data())); | 674 providers_.template_url_service()->search_terms_data())); |
| 688 if (!suggest_url.is_valid()) | 675 if (!suggest_url.is_valid()) |
| 689 return NULL; | 676 return NULL; |
| 690 // Send the current page URL if user setting and URL requirements are met and | 677 // Send the current page URL if user setting and URL requirements are met and |
| 691 // the user is in the field trial. | 678 // the user is in the field trial. |
| 692 if (CanSendURL(current_page_url_, suggest_url, template_url, | 679 if (CanSendURL(current_page_url_, suggest_url, template_url, |
| 693 input.current_page_classification(), | 680 input.current_page_classification(), |
| 694 template_url_service_->search_terms_data(), profile_) && | 681 template_url_service_->search_terms_data(), delegate_.get()) && |
| 695 OmniboxFieldTrial::InZeroSuggestAfterTypingFieldTrial()) { | 682 OmniboxFieldTrial::InZeroSuggestAfterTypingFieldTrial()) { |
| 696 search_term_args.current_page_url = current_page_url_.spec(); | 683 search_term_args.current_page_url = current_page_url_.spec(); |
| 697 // Create the suggest URL again with the current page URL. | 684 // Create the suggest URL again with the current page URL. |
| 698 suggest_url = GURL(template_url->suggestions_url_ref().ReplaceSearchTerms( | 685 suggest_url = GURL(template_url->suggestions_url_ref().ReplaceSearchTerms( |
| 699 search_term_args, | 686 search_term_args, |
| 700 providers_.template_url_service()->search_terms_data())); | 687 providers_.template_url_service()->search_terms_data())); |
| 701 } | 688 } |
| 702 | 689 |
| 703 suggest_results_pending_++; | 690 suggest_results_pending_++; |
| 704 LogOmniboxSuggestRequest(REQUEST_SENT); | 691 LogOmniboxSuggestRequest(REQUEST_SENT); |
| 705 | 692 |
| 706 net::URLFetcher* fetcher = | 693 net::URLFetcher* fetcher = |
| 707 net::URLFetcher::Create(id, suggest_url, net::URLFetcher::GET, this); | 694 net::URLFetcher::Create(id, suggest_url, net::URLFetcher::GET, this); |
| 708 fetcher->SetRequestContext(profile_->GetRequestContext()); | 695 fetcher->SetRequestContext(delegate_->GetRequestContext()); |
| 709 fetcher->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES); | 696 fetcher->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES); |
| 710 // Add Chrome experiment state to the request headers. | 697 // Add Chrome experiment state to the request headers. |
| 711 net::HttpRequestHeaders headers; | 698 net::HttpRequestHeaders headers; |
| 712 variations::VariationsHttpHeaderProvider::GetInstance()->AppendHeaders( | 699 variations::VariationsHttpHeaderProvider::GetInstance()->AppendHeaders( |
| 713 fetcher->GetOriginalURL(), profile_->IsOffTheRecord(), false, &headers); | 700 fetcher->GetOriginalURL(), delegate_->IsOffTheRecord(), false, &headers); |
| 714 fetcher->SetExtraRequestHeaders(headers.ToString()); | 701 fetcher->SetExtraRequestHeaders(headers.ToString()); |
| 715 fetcher->Start(); | 702 fetcher->Start(); |
| 716 return fetcher; | 703 return fetcher; |
| 717 } | 704 } |
| 718 | 705 |
| 719 void SearchProvider::ConvertResultsToAutocompleteMatches() { | 706 void SearchProvider::ConvertResultsToAutocompleteMatches() { |
| 720 // Convert all the results to matches and add them to a map, so we can keep | 707 // Convert all the results to matches and add them to a map, so we can keep |
| 721 // the most relevant match for each result. | 708 // the most relevant match for each result. |
| 722 base::TimeTicks start_time(base::TimeTicks::Now()); | 709 base::TimeTicks start_time(base::TimeTicks::Now()); |
| 723 MatchMap map; | 710 MatchMap map; |
| (...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 986 // NOTE: We don't check for autocompleting to URLs in the following cases: | 973 // NOTE: We don't check for autocompleting to URLs in the following cases: |
| 987 // * When inline autocomplete is disabled, we won't be inline autocompleting | 974 // * When inline autocomplete is disabled, we won't be inline autocompleting |
| 988 // this term, so we don't need to worry about confusion as much. This | 975 // this term, so we don't need to worry about confusion as much. This |
| 989 // also prevents calling Classify() again from inside the classifier | 976 // also prevents calling Classify() again from inside the classifier |
| 990 // (which will corrupt state and likely crash), since the classifier | 977 // (which will corrupt state and likely crash), since the classifier |
| 991 // always disables inline autocomplete. | 978 // always disables inline autocomplete. |
| 992 // * When the user has typed the whole string before as a query, then it's | 979 // * When the user has typed the whole string before as a query, then it's |
| 993 // likely the user has no expectation that term should be interpreted as | 980 // likely the user has no expectation that term should be interpreted as |
| 994 // as a URL, so we need not do anything special to preserve user | 981 // as a URL, so we need not do anything special to preserve user |
| 995 // expectation. | 982 // expectation. |
| 996 AutocompleteClassifier* classifier = | |
| 997 AutocompleteClassifierFactory::GetForProfile(profile_); | |
| 998 int last_relevance = 0; | 983 int last_relevance = 0; |
| 999 if (!base_prevent_inline_autocomplete && !found_what_you_typed_match && | 984 if (!base_prevent_inline_autocomplete && !found_what_you_typed_match && |
| 1000 classifier && (scored_results.front().relevance() >= 1200)) { | 985 scored_results.front().relevance() >= 1200) { |
| 1001 AutocompleteMatch match; | 986 AutocompleteMatch match; |
| 1002 classifier->Classify(scored_results.front().suggestion(), false, false, | 987 delegate_->Classify(scored_results.front().suggestion(), false, false, |
| 1003 input_.current_page_classification(), &match, NULL); | 988 input_.current_page_classification(), &match, NULL); |
| 1004 // Demote this match that would normally be interpreted as a URL to have | 989 // Demote this match that would normally be interpreted as a URL to have |
| 1005 // the highest score a previously-issued search query could have when | 990 // the highest score a previously-issued search query could have when |
| 1006 // scoring with the non-aggressive method. A consequence of demoting | 991 // scoring with the non-aggressive method. A consequence of demoting |
| 1007 // by revising |last_relevance| is that this match and all following | 992 // by revising |last_relevance| is that this match and all following |
| 1008 // matches get demoted; the relative order of matches is preserved. | 993 // matches get demoted; the relative order of matches is preserved. |
| 1009 // One could imagine demoting only those matches that might cause | 994 // One could imagine demoting only those matches that might cause |
| 1010 // confusion (which, by the way, might change the relative order of | 995 // confusion (which, by the way, might change the relative order of |
| 1011 // matches. We have decided to go with the simple demote-all approach | 996 // matches. We have decided to go with the simple demote-all approach |
| 1012 // because selective demotion requires multiple Classify() calls and | 997 // because selective demotion requires multiple Classify() calls and |
| 1013 // such calls can be expensive (as expensive as running the whole | 998 // such calls can be expensive (as expensive as running the whole |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1163 // scheme. | 1148 // scheme. |
| 1164 const URLPrefix* prefix = | 1149 const URLPrefix* prefix = |
| 1165 URLPrefix::BestURLPrefix(navigation.formatted_url(), input); | 1150 URLPrefix::BestURLPrefix(navigation.formatted_url(), input); |
| 1166 size_t match_start = (prefix == NULL) ? | 1151 size_t match_start = (prefix == NULL) ? |
| 1167 navigation.formatted_url().find(input) : prefix->prefix.length(); | 1152 navigation.formatted_url().find(input) : prefix->prefix.length(); |
| 1168 bool trim_http = !AutocompleteInput::HasHTTPScheme(input) && | 1153 bool trim_http = !AutocompleteInput::HasHTTPScheme(input) && |
| 1169 (!prefix || (match_start != 0)); | 1154 (!prefix || (match_start != 0)); |
| 1170 const net::FormatUrlTypes format_types = | 1155 const net::FormatUrlTypes format_types = |
| 1171 net::kFormatUrlOmitAll & ~(trim_http ? 0 : net::kFormatUrlOmitHTTP); | 1156 net::kFormatUrlOmitAll & ~(trim_http ? 0 : net::kFormatUrlOmitHTTP); |
| 1172 | 1157 |
| 1173 const std::string languages( | 1158 const std::string languages(delegate_->GetAcceptLanguages()); |
| 1174 profile_->GetPrefs()->GetString(prefs::kAcceptLanguages)); | |
| 1175 size_t inline_autocomplete_offset = (prefix == NULL) ? | 1159 size_t inline_autocomplete_offset = (prefix == NULL) ? |
| 1176 base::string16::npos : (match_start + input.length()); | 1160 base::string16::npos : (match_start + input.length()); |
| 1177 match.fill_into_edit += | 1161 match.fill_into_edit += |
| 1178 AutocompleteInput::FormattedStringWithEquivalentMeaning( | 1162 AutocompleteInput::FormattedStringWithEquivalentMeaning( |
| 1179 navigation.url(), | 1163 navigation.url(), |
| 1180 net::FormatUrl(navigation.url(), languages, format_types, | 1164 net::FormatUrl(navigation.url(), languages, format_types, |
| 1181 net::UnescapeRule::SPACES, NULL, NULL, | 1165 net::UnescapeRule::SPACES, NULL, NULL, |
| 1182 &inline_autocomplete_offset), | 1166 &inline_autocomplete_offset), |
| 1183 ChromeAutocompleteSchemeClassifier(profile_)); | 1167 delegate_->GetSchemeClassifier()); |
| 1184 // Preserve the forced query '?' prefix in |match.fill_into_edit|. | 1168 // Preserve the forced query '?' prefix in |match.fill_into_edit|. |
| 1185 // Otherwise, user edits to a suggestion would show non-Search results. | 1169 // Otherwise, user edits to a suggestion would show non-Search results. |
| 1186 if (input_.type() == metrics::OmniboxInputType::FORCED_QUERY) { | 1170 if (input_.type() == metrics::OmniboxInputType::FORCED_QUERY) { |
| 1187 match.fill_into_edit.insert(0, base::ASCIIToUTF16("?")); | 1171 match.fill_into_edit.insert(0, base::ASCIIToUTF16("?")); |
| 1188 if (inline_autocomplete_offset != base::string16::npos) | 1172 if (inline_autocomplete_offset != base::string16::npos) |
| 1189 ++inline_autocomplete_offset; | 1173 ++inline_autocomplete_offset; |
| 1190 } | 1174 } |
| 1191 if (inline_autocomplete_offset != base::string16::npos) { | 1175 if (inline_autocomplete_offset != base::string16::npos) { |
| 1192 DCHECK(inline_autocomplete_offset <= match.fill_into_edit.length()); | 1176 DCHECK(inline_autocomplete_offset <= match.fill_into_edit.length()); |
| 1193 match.inline_autocompletion = | 1177 match.inline_autocompletion = |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1263 match->fill_into_edit.empty()) | 1247 match->fill_into_edit.empty()) |
| 1264 return; | 1248 return; |
| 1265 | 1249 |
| 1266 // Valid answer encountered, cache it for further queries. | 1250 // Valid answer encountered, cache it for further queries. |
| 1267 answers_cache_.UpdateRecentAnswers(match->fill_into_edit, match->answer_type); | 1251 answers_cache_.UpdateRecentAnswers(match->fill_into_edit, match->answer_type); |
| 1268 } | 1252 } |
| 1269 | 1253 |
| 1270 void SearchProvider::DoAnswersQuery(const AutocompleteInput& input) { | 1254 void SearchProvider::DoAnswersQuery(const AutocompleteInput& input) { |
| 1271 prefetch_data_ = answers_cache_.GetTopAnswerEntry(input.text()); | 1255 prefetch_data_ = answers_cache_.GetTopAnswerEntry(input.text()); |
| 1272 } | 1256 } |
| OLD | NEW |