| 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/callback.h" | 10 #include "base/callback.h" | 
| (...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 220 | 220 | 
| 221   instant_finalized_ = | 221   instant_finalized_ = | 
| 222       (input.matches_requested() != AutocompleteInput::ALL_MATCHES); | 222       (input.matches_requested() != AutocompleteInput::ALL_MATCHES); | 
| 223 | 223 | 
| 224   // Can't return search/suggest results for bogus input or without a profile. | 224   // Can't return search/suggest results for bogus input or without a profile. | 
| 225   if (!profile_ || (input.type() == AutocompleteInput::INVALID)) { | 225   if (!profile_ || (input.type() == AutocompleteInput::INVALID)) { | 
| 226     Stop(false); | 226     Stop(false); | 
| 227     return; | 227     return; | 
| 228   } | 228   } | 
| 229 | 229 | 
| 230   keyword_input_text_.clear(); | 230   keyword_input_ = input; | 
| 231   const TemplateURL* keyword_provider = | 231   const TemplateURL* keyword_provider = | 
| 232       KeywordProvider::GetSubstitutingTemplateURLForInput(profile_, input, | 232       KeywordProvider::GetSubstitutingTemplateURLForInput(model, | 
| 233                                                           &keyword_input_text_); | 233                                                           &keyword_input_); | 
| 234   if (keyword_input_text_.empty()) | 234   if (keyword_provider == NULL) | 
|  | 235     keyword_input_.Clear(); | 
|  | 236   else if (keyword_input_.text().empty()) | 
| 235     keyword_provider = NULL; | 237     keyword_provider = NULL; | 
| 236 | 238 | 
| 237   const TemplateURL* default_provider = model->GetDefaultSearchProvider(); | 239   const TemplateURL* default_provider = model->GetDefaultSearchProvider(); | 
| 238   if (default_provider && !default_provider->SupportsReplacement()) | 240   if (default_provider && !default_provider->SupportsReplacement()) | 
| 239     default_provider = NULL; | 241     default_provider = NULL; | 
| 240 | 242 | 
| 241   if (keyword_provider == default_provider) | 243   if (keyword_provider == default_provider) | 
| 242     default_provider = NULL;  // No use in querying the same provider twice. | 244     default_provider = NULL;  // No use in querying the same provider twice. | 
| 243 | 245 | 
| 244   if (!default_provider && !keyword_provider) { | 246   if (!default_provider && !keyword_provider) { | 
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 323     return a.relevance() > b.relevance(); | 325     return a.relevance() > b.relevance(); | 
| 324   } | 326   } | 
| 325 }; | 327 }; | 
| 326 | 328 | 
| 327 void SearchProvider::Run() { | 329 void SearchProvider::Run() { | 
| 328   // Start a new request with the current input. | 330   // Start a new request with the current input. | 
| 329   suggest_results_pending_ = 0; | 331   suggest_results_pending_ = 0; | 
| 330   time_suggest_request_sent_ = base::TimeTicks::Now(); | 332   time_suggest_request_sent_ = base::TimeTicks::Now(); | 
| 331 | 333 | 
| 332   default_fetcher_.reset(CreateSuggestFetcher(kDefaultProviderURLFetcherID, | 334   default_fetcher_.reset(CreateSuggestFetcher(kDefaultProviderURLFetcherID, | 
| 333       providers_.GetDefaultProviderURL(), input_.text())); | 335       providers_.GetDefaultProviderURL(), input_)); | 
| 334   keyword_fetcher_.reset(CreateSuggestFetcher(kKeywordProviderURLFetcherID, | 336   keyword_fetcher_.reset(CreateSuggestFetcher(kKeywordProviderURLFetcherID, | 
| 335       providers_.GetKeywordProviderURL(), keyword_input_text_)); | 337       providers_.GetKeywordProviderURL(), keyword_input_)); | 
| 336 | 338 | 
| 337   // Both the above can fail if the providers have been modified or deleted | 339   // Both the above can fail if the providers have been modified or deleted | 
| 338   // since the query began. | 340   // since the query began. | 
| 339   if (suggest_results_pending_ == 0) { | 341   if (suggest_results_pending_ == 0) { | 
| 340     UpdateDone(); | 342     UpdateDone(); | 
| 341     // We only need to update the listener if we're actually done. | 343     // We only need to update the listener if we're actually done. | 
| 342     if (done_) | 344     if (done_) | 
| 343       listener_->OnProviderUpdate(false); | 345       listener_->OnProviderUpdate(false); | 
| 344   } | 346   } | 
| 345 } | 347 } | 
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 463   // database. | 465   // database. | 
| 464   int num_matches = kMaxMatches * 5; | 466   int num_matches = kMaxMatches * 5; | 
| 465   const TemplateURL* default_url = providers_.GetDefaultProviderURL(); | 467   const TemplateURL* default_url = providers_.GetDefaultProviderURL(); | 
| 466   if (default_url) { | 468   if (default_url) { | 
| 467     url_db->GetMostRecentKeywordSearchTerms(default_url->id(), input_.text(), | 469     url_db->GetMostRecentKeywordSearchTerms(default_url->id(), input_.text(), | 
| 468         num_matches, &default_history_results_); | 470         num_matches, &default_history_results_); | 
| 469   } | 471   } | 
| 470   const TemplateURL* keyword_url = providers_.GetKeywordProviderURL(); | 472   const TemplateURL* keyword_url = providers_.GetKeywordProviderURL(); | 
| 471   if (keyword_url) { | 473   if (keyword_url) { | 
| 472     url_db->GetMostRecentKeywordSearchTerms(keyword_url->id(), | 474     url_db->GetMostRecentKeywordSearchTerms(keyword_url->id(), | 
| 473         keyword_input_text_, num_matches, &keyword_history_results_); | 475         keyword_input_.text(), num_matches, &keyword_history_results_); | 
| 474   } | 476   } | 
| 475 } | 477 } | 
| 476 | 478 | 
| 477 void SearchProvider::StartOrStopSuggestQuery(bool minimal_changes) { | 479 void SearchProvider::StartOrStopSuggestQuery(bool minimal_changes) { | 
| 478   if (!IsQuerySuitableForSuggest()) { | 480   if (!IsQuerySuitableForSuggest()) { | 
| 479     StopSuggest(); | 481     StopSuggest(); | 
| 480     ClearResults(); | 482     ClearResults(); | 
| 481     return; | 483     return; | 
| 482   } | 484   } | 
| 483 | 485 | 
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 584   keyword_suggest_results_.clear(); | 586   keyword_suggest_results_.clear(); | 
| 585   default_suggest_results_.clear(); | 587   default_suggest_results_.clear(); | 
| 586   keyword_navigation_results_.clear(); | 588   keyword_navigation_results_.clear(); | 
| 587   default_navigation_results_.clear(); | 589   default_navigation_results_.clear(); | 
| 588   has_suggested_relevance_ = false; | 590   has_suggested_relevance_ = false; | 
| 589   verbatim_relevance_ = -1; | 591   verbatim_relevance_ = -1; | 
| 590   have_suggest_results_ = false; | 592   have_suggest_results_ = false; | 
| 591 } | 593 } | 
| 592 | 594 | 
| 593 void SearchProvider::RemoveStaleResults() { | 595 void SearchProvider::RemoveStaleResults() { | 
| 594   // Keyword provider results should match |keyword_input_text_|, unless | 596   // Keyword provider results should match |keyword_input_.text()|, unless | 
| 595   // the input was just changed to non-keyword mode; in that case, compare | 597   // the input was just changed to non-keyword mode; in that case, compare | 
| 596   // against |input_.text()|. | 598   // against |input_.text()|. | 
| 597   const string16& keyword_input = | 599   const string16& keyword_input = | 
| 598       !keyword_input_text_.empty() ? keyword_input_text_ : input_.text(); | 600       !keyword_input_.text().empty() ? keyword_input_.text() : input_.text(); | 
| 599   RemoveStaleSuggestResults(&keyword_suggest_results_, keyword_input); | 601   RemoveStaleSuggestResults(&keyword_suggest_results_, keyword_input); | 
| 600   RemoveStaleSuggestResults(&default_suggest_results_, input_.text()); | 602   RemoveStaleSuggestResults(&default_suggest_results_, input_.text()); | 
| 601   RemoveStaleNavigationResults(&keyword_navigation_results_, keyword_input); | 603   RemoveStaleNavigationResults(&keyword_navigation_results_, keyword_input); | 
| 602   RemoveStaleNavigationResults(&default_navigation_results_, input_.text()); | 604   RemoveStaleNavigationResults(&default_navigation_results_, input_.text()); | 
| 603 } | 605 } | 
| 604 | 606 | 
| 605 // static | 607 // static | 
| 606 void SearchProvider::RemoveStaleSuggestResults(SuggestResults* list, | 608 void SearchProvider::RemoveStaleSuggestResults(SuggestResults* list, | 
| 607                                                const string16& input) { | 609                                                const string16& input) { | 
| 608   for (SuggestResults::iterator i = list->begin(); i < list->end();) | 610   for (SuggestResults::iterator i = list->begin(); i < list->end();) | 
| (...skipping 30 matching lines...) Expand all  Loading... | 
| 639                                                         bool is_keyword) { | 641                                                         bool is_keyword) { | 
| 640   for (size_t i = 0; i < list->size(); ++i) { | 642   for (size_t i = 0; i < list->size(); ++i) { | 
| 641     (*list)[i].set_relevance(CalculateRelevanceForNavigation(is_keyword) + | 643     (*list)[i].set_relevance(CalculateRelevanceForNavigation(is_keyword) + | 
| 642                              (list->size() - i - 1)); | 644                              (list->size() - i - 1)); | 
| 643   } | 645   } | 
| 644 } | 646 } | 
| 645 | 647 | 
| 646 net::URLFetcher* SearchProvider::CreateSuggestFetcher( | 648 net::URLFetcher* SearchProvider::CreateSuggestFetcher( | 
| 647     int id, | 649     int id, | 
| 648     const TemplateURL* template_url, | 650     const TemplateURL* template_url, | 
| 649     const string16& text) { | 651     const AutocompleteInput& input) { | 
| 650   if (!template_url || template_url->suggestions_url().empty()) | 652   if (!template_url || template_url->suggestions_url().empty()) | 
| 651     return NULL; | 653     return NULL; | 
| 652 | 654 | 
| 653   // Bail if the suggestion URL is invalid with the given replacements. | 655   // Bail if the suggestion URL is invalid with the given replacements. | 
| 654   TemplateURLRef::SearchTermsArgs search_term_args(text); | 656   TemplateURLRef::SearchTermsArgs search_term_args(input.text()); | 
| 655   search_term_args.cursor_position = input_.cursor_position(); | 657   search_term_args.cursor_position = input.cursor_position(); | 
| 656   GURL suggest_url(template_url->suggestions_url_ref().ReplaceSearchTerms( | 658   GURL suggest_url(template_url->suggestions_url_ref().ReplaceSearchTerms( | 
| 657       search_term_args)); | 659       search_term_args)); | 
| 658   if (!suggest_url.is_valid()) | 660   if (!suggest_url.is_valid()) | 
| 659     return NULL; | 661     return NULL; | 
| 660 | 662 | 
| 661   suggest_results_pending_++; | 663   suggest_results_pending_++; | 
| 662   LogOmniboxSuggestRequest(REQUEST_SENT); | 664   LogOmniboxSuggestRequest(REQUEST_SENT); | 
| 663 | 665 | 
| 664   net::URLFetcher* fetcher = | 666   net::URLFetcher* fetcher = | 
| 665       net::URLFetcher::Create(id, suggest_url, net::URLFetcher::GET, this); | 667       net::URLFetcher::Create(id, suggest_url, net::URLFetcher::GET, this); | 
| 666   fetcher->SetRequestContext(profile_->GetRequestContext()); | 668   fetcher->SetRequestContext(profile_->GetRequestContext()); | 
| 667   fetcher->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES); | 669   fetcher->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES); | 
| 668   // Add Chrome experiment state to the request headers. | 670   // Add Chrome experiment state to the request headers. | 
| 669   net::HttpRequestHeaders headers; | 671   net::HttpRequestHeaders headers; | 
| 670   chrome_variations::VariationsHttpHeaderProvider::GetInstance()->AppendHeaders( | 672   chrome_variations::VariationsHttpHeaderProvider::GetInstance()->AppendHeaders( | 
| 671       fetcher->GetOriginalURL(), profile_->IsOffTheRecord(), false, &headers); | 673       fetcher->GetOriginalURL(), profile_->IsOffTheRecord(), false, &headers); | 
| 672   fetcher->SetExtraRequestHeaders(headers.ToString()); | 674   fetcher->SetExtraRequestHeaders(headers.ToString()); | 
| 673   fetcher->Start(); | 675   fetcher->Start(); | 
| 674   return fetcher; | 676   return fetcher; | 
| 675 } | 677 } | 
| 676 | 678 | 
| 677 bool SearchProvider::ParseSuggestResults(Value* root_val, bool is_keyword) { | 679 bool SearchProvider::ParseSuggestResults(Value* root_val, bool is_keyword) { | 
| 678   // TODO(pkasting): Fix |have_suggest_results_|; see http://crbug.com/130631 | 680   // TODO(pkasting): Fix |have_suggest_results_|; see http://crbug.com/130631 | 
| 679   have_suggest_results_ = false; | 681   have_suggest_results_ = false; | 
| 680 | 682 | 
| 681   string16 query; | 683   string16 query; | 
| 682   ListValue* root_list = NULL; | 684   ListValue* root_list = NULL; | 
| 683   ListValue* results = NULL; | 685   ListValue* results = NULL; | 
| 684   const string16& input_text = is_keyword ? keyword_input_text_ : input_.text(); | 686   const string16& input_text = | 
|  | 687       is_keyword ? keyword_input_.text() : input_.text(); | 
| 685   if (!root_val->GetAsList(&root_list) || !root_list->GetString(0, &query) || | 688   if (!root_val->GetAsList(&root_list) || !root_list->GetString(0, &query) || | 
| 686       (query != input_text) || !root_list->GetList(1, &results)) | 689       (query != input_text) || !root_list->GetList(1, &results)) | 
| 687     return false; | 690     return false; | 
| 688 | 691 | 
| 689   // 3rd element: Description list. | 692   // 3rd element: Description list. | 
| 690   ListValue* descriptions = NULL; | 693   ListValue* descriptions = NULL; | 
| 691   root_list->GetList(2, &descriptions); | 694   root_list->GetList(2, &descriptions); | 
| 692 | 695 | 
| 693   // 4th element: Disregard the query URL list for now. | 696   // 4th element: Disregard the query URL list for now. | 
| 694 | 697 | 
| (...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 939 | 942 | 
| 940 void SearchProvider::AddHistoryResultsToMap(const HistoryResults& results, | 943 void SearchProvider::AddHistoryResultsToMap(const HistoryResults& results, | 
| 941                                             bool is_keyword, | 944                                             bool is_keyword, | 
| 942                                             int did_not_accept_suggestion, | 945                                             int did_not_accept_suggestion, | 
| 943                                             MatchMap* map) { | 946                                             MatchMap* map) { | 
| 944   if (results.empty()) | 947   if (results.empty()) | 
| 945     return; | 948     return; | 
| 946 | 949 | 
| 947   bool prevent_inline_autocomplete = input_.prevent_inline_autocomplete() || | 950   bool prevent_inline_autocomplete = input_.prevent_inline_autocomplete() || | 
| 948       (input_.type() == AutocompleteInput::URL); | 951       (input_.type() == AutocompleteInput::URL); | 
| 949   const string16& input_text = is_keyword ? keyword_input_text_ : input_.text(); | 952   const string16& input_text = | 
|  | 953       is_keyword ? keyword_input_.text() : input_.text(); | 
| 950   bool input_multiple_words = HasMultipleWords(input_text); | 954   bool input_multiple_words = HasMultipleWords(input_text); | 
| 951 | 955 | 
| 952   SuggestResults scored_results; | 956   SuggestResults scored_results; | 
| 953   if (!prevent_inline_autocomplete && input_multiple_words) { | 957   if (!prevent_inline_autocomplete && input_multiple_words) { | 
| 954     // ScoreHistoryResults() allows autocompletion of multi-word, 1-visit | 958     // ScoreHistoryResults() allows autocompletion of multi-word, 1-visit | 
| 955     // queries if the input also has multiple words.  But if we were already | 959     // queries if the input also has multiple words.  But if we were already | 
| 956     // autocompleting a multi-word, multi-visit query, and the current input is | 960     // autocompleting a multi-word, multi-visit query, and the current input is | 
| 957     // still a prefix of it, then changing the autocompletion suddenly feels | 961     // still a prefix of it, then changing the autocompletion suddenly feels | 
| 958     // wrong.  To detect this case, first score as if only one word has been | 962     // wrong.  To detect this case, first score as if only one word has been | 
| 959     // typed, then check for a best result that is an autocompleted, multi-word | 963     // typed, then check for a best result that is an autocompleted, multi-word | 
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1032       i->set_relevance(last_relevance - 1); | 1036       i->set_relevance(last_relevance - 1); | 
| 1033     last_relevance = i->relevance(); | 1037     last_relevance = i->relevance(); | 
| 1034   } | 1038   } | 
| 1035 | 1039 | 
| 1036   return scored_results; | 1040   return scored_results; | 
| 1037 } | 1041 } | 
| 1038 | 1042 | 
| 1039 void SearchProvider::AddSuggestResultsToMap(const SuggestResults& results, | 1043 void SearchProvider::AddSuggestResultsToMap(const SuggestResults& results, | 
| 1040                                             bool is_keyword, | 1044                                             bool is_keyword, | 
| 1041                                             MatchMap* map) { | 1045                                             MatchMap* map) { | 
| 1042   const string16& input_text = is_keyword ? keyword_input_text_ : input_.text(); | 1046   const string16& input_text = | 
|  | 1047       is_keyword ? keyword_input_.text() : input_.text(); | 
| 1043   for (size_t i = 0; i < results.size(); ++i) { | 1048   for (size_t i = 0; i < results.size(); ++i) { | 
| 1044     AddMatchToMap(results[i].suggestion(), input_text, results[i].relevance(), | 1049     AddMatchToMap(results[i].suggestion(), input_text, results[i].relevance(), | 
| 1045                   AutocompleteMatch::SEARCH_SUGGEST, i, is_keyword, map); | 1050                   AutocompleteMatch::SEARCH_SUGGEST, i, is_keyword, map); | 
| 1046   } | 1051   } | 
| 1047 } | 1052 } | 
| 1048 | 1053 | 
| 1049 int SearchProvider::GetVerbatimRelevance() const { | 1054 int SearchProvider::GetVerbatimRelevance() const { | 
| 1050   // Use the suggested verbatim relevance score if it is non-negative (valid), | 1055   // Use the suggested verbatim relevance score if it is non-negative (valid), | 
| 1051   // if inline autocomplete isn't prevented (always show verbatim on backspace), | 1056   // if inline autocomplete isn't prevented (always show verbatim on backspace), | 
| 1052   // and if it won't suppress verbatim, leaving no default provider matches. | 1057   // and if it won't suppress verbatim, leaving no default provider matches. | 
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1230   // results sorted by recency, this means we'll pick the most recent such | 1235   // results sorted by recency, this means we'll pick the most recent such | 
| 1231   // result even if the precision of our relevance score is too low to | 1236   // result even if the precision of our relevance score is too low to | 
| 1232   // distinguish the two. | 1237   // distinguish the two. | 
| 1233   if (!i.second && (match.relevance > i.first->second.relevance)) | 1238   if (!i.second && (match.relevance > i.first->second.relevance)) | 
| 1234     i.first->second = match; | 1239     i.first->second = match; | 
| 1235 } | 1240 } | 
| 1236 | 1241 | 
| 1237 AutocompleteMatch SearchProvider::NavigationToMatch( | 1242 AutocompleteMatch SearchProvider::NavigationToMatch( | 
| 1238     const NavigationResult& navigation, | 1243     const NavigationResult& navigation, | 
| 1239     bool is_keyword) { | 1244     bool is_keyword) { | 
| 1240   const string16& input = is_keyword ? keyword_input_text_ : input_.text(); | 1245   const string16& input = is_keyword ? keyword_input_.text() : input_.text(); | 
| 1241   AutocompleteMatch match(this, navigation.relevance(), false, | 1246   AutocompleteMatch match(this, navigation.relevance(), false, | 
| 1242                           AutocompleteMatch::NAVSUGGEST); | 1247                           AutocompleteMatch::NAVSUGGEST); | 
| 1243   match.destination_url = navigation.url(); | 1248   match.destination_url = navigation.url(); | 
| 1244 | 1249 | 
| 1245   // First look for the user's input inside the fill_into_edit as it would be | 1250   // First look for the user's input inside the fill_into_edit as it would be | 
| 1246   // without trimming the scheme, so we can find matches at the beginning of the | 1251   // without trimming the scheme, so we can find matches at the beginning of the | 
| 1247   // scheme. | 1252   // scheme. | 
| 1248   const string16 untrimmed_fill_into_edit( | 1253   const string16 untrimmed_fill_into_edit( | 
| 1249       AutocompleteInput::FormattedStringWithEquivalentMeaning(navigation.url(), | 1254       AutocompleteInput::FormattedStringWithEquivalentMeaning(navigation.url(), | 
| 1250           StringForURLDisplay(navigation.url(), true, false))); | 1255           StringForURLDisplay(navigation.url(), true, false))); | 
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1297 } | 1302 } | 
| 1298 | 1303 | 
| 1299 void SearchProvider::UpdateDone() { | 1304 void SearchProvider::UpdateDone() { | 
| 1300   // We're done when the timer isn't running, there are no suggest queries | 1305   // We're done when the timer isn't running, there are no suggest queries | 
| 1301   // pending, and we're not waiting on instant. | 1306   // pending, and we're not waiting on instant. | 
| 1302   done_ = (!timer_.IsRunning() && (suggest_results_pending_ == 0) && | 1307   done_ = (!timer_.IsRunning() && (suggest_results_pending_ == 0) && | 
| 1303            (instant_finalized_ || | 1308            (instant_finalized_ || | 
| 1304             (!chrome::BrowserInstantController::IsInstantEnabled(profile_) && | 1309             (!chrome::BrowserInstantController::IsInstantEnabled(profile_) && | 
| 1305              !chrome::search::IsInstantExtendedAPIEnabled(profile_)))); | 1310              !chrome::search::IsInstantExtendedAPIEnabled(profile_)))); | 
| 1306 } | 1311 } | 
| OLD | NEW | 
|---|