| 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 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 467 // database. | 469 // database. |
| 468 int num_matches = kMaxMatches * 5; | 470 int num_matches = kMaxMatches * 5; |
| 469 const TemplateURL* default_url = providers_.GetDefaultProviderURL(); | 471 const TemplateURL* default_url = providers_.GetDefaultProviderURL(); |
| 470 if (default_url) { | 472 if (default_url) { |
| 471 url_db->GetMostRecentKeywordSearchTerms(default_url->id(), input_.text(), | 473 url_db->GetMostRecentKeywordSearchTerms(default_url->id(), input_.text(), |
| 472 num_matches, &default_history_results_); | 474 num_matches, &default_history_results_); |
| 473 } | 475 } |
| 474 const TemplateURL* keyword_url = providers_.GetKeywordProviderURL(); | 476 const TemplateURL* keyword_url = providers_.GetKeywordProviderURL(); |
| 475 if (keyword_url) { | 477 if (keyword_url) { |
| 476 url_db->GetMostRecentKeywordSearchTerms(keyword_url->id(), | 478 url_db->GetMostRecentKeywordSearchTerms(keyword_url->id(), |
| 477 keyword_input_text_, num_matches, &keyword_history_results_); | 479 keyword_input_.text(), num_matches, &keyword_history_results_); |
| 478 } | 480 } |
| 479 } | 481 } |
| 480 | 482 |
| 481 void SearchProvider::StartOrStopSuggestQuery(bool minimal_changes) { | 483 void SearchProvider::StartOrStopSuggestQuery(bool minimal_changes) { |
| 482 if (!IsQuerySuitableForSuggest()) { | 484 if (!IsQuerySuitableForSuggest()) { |
| 483 StopSuggest(); | 485 StopSuggest(); |
| 484 ClearResults(); | 486 ClearResults(); |
| 485 return; | 487 return; |
| 486 } | 488 } |
| 487 | 489 |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 588 keyword_suggest_results_.clear(); | 590 keyword_suggest_results_.clear(); |
| 589 default_suggest_results_.clear(); | 591 default_suggest_results_.clear(); |
| 590 keyword_navigation_results_.clear(); | 592 keyword_navigation_results_.clear(); |
| 591 default_navigation_results_.clear(); | 593 default_navigation_results_.clear(); |
| 592 has_suggested_relevance_ = false; | 594 has_suggested_relevance_ = false; |
| 593 verbatim_relevance_ = -1; | 595 verbatim_relevance_ = -1; |
| 594 have_suggest_results_ = false; | 596 have_suggest_results_ = false; |
| 595 } | 597 } |
| 596 | 598 |
| 597 void SearchProvider::RemoveStaleResults() { | 599 void SearchProvider::RemoveStaleResults() { |
| 598 // Keyword provider results should match |keyword_input_text_|, unless | 600 // Keyword provider results should match |keyword_input_.text()|, unless |
| 599 // the input was just changed to non-keyword mode; in that case, compare | 601 // the input was just changed to non-keyword mode; in that case, compare |
| 600 // against |input_.text()|. | 602 // against |input_.text()|. |
| 601 const string16& keyword_input = | 603 const string16& keyword_input = |
| 602 !keyword_input_text_.empty() ? keyword_input_text_ : input_.text(); | 604 !keyword_input_.text().empty() ? keyword_input_.text() : input_.text(); |
| 603 RemoveStaleSuggestResults(&keyword_suggest_results_, keyword_input); | 605 RemoveStaleSuggestResults(&keyword_suggest_results_, keyword_input); |
| 604 RemoveStaleSuggestResults(&default_suggest_results_, input_.text()); | 606 RemoveStaleSuggestResults(&default_suggest_results_, input_.text()); |
| 605 RemoveStaleNavigationResults(&keyword_navigation_results_, keyword_input); | 607 RemoveStaleNavigationResults(&keyword_navigation_results_, keyword_input); |
| 606 RemoveStaleNavigationResults(&default_navigation_results_, input_.text()); | 608 RemoveStaleNavigationResults(&default_navigation_results_, input_.text()); |
| 607 } | 609 } |
| 608 | 610 |
| 609 // static | 611 // static |
| 610 void SearchProvider::RemoveStaleSuggestResults(SuggestResults* list, | 612 void SearchProvider::RemoveStaleSuggestResults(SuggestResults* list, |
| 611 const string16& input) { | 613 const string16& input) { |
| 612 for (SuggestResults::iterator i = list->begin(); i < list->end();) | 614 for (SuggestResults::iterator i = list->begin(); i < list->end();) |
| (...skipping 30 matching lines...) Expand all Loading... |
| 643 bool is_keyword) { | 645 bool is_keyword) { |
| 644 for (size_t i = 0; i < list->size(); ++i) { | 646 for (size_t i = 0; i < list->size(); ++i) { |
| 645 (*list)[i].set_relevance(CalculateRelevanceForNavigation(is_keyword) + | 647 (*list)[i].set_relevance(CalculateRelevanceForNavigation(is_keyword) + |
| 646 (list->size() - i - 1)); | 648 (list->size() - i - 1)); |
| 647 } | 649 } |
| 648 } | 650 } |
| 649 | 651 |
| 650 net::URLFetcher* SearchProvider::CreateSuggestFetcher( | 652 net::URLFetcher* SearchProvider::CreateSuggestFetcher( |
| 651 int id, | 653 int id, |
| 652 const TemplateURL* template_url, | 654 const TemplateURL* template_url, |
| 653 const string16& text) { | 655 const AutocompleteInput& input) { |
| 654 if (!template_url || template_url->suggestions_url().empty()) | 656 if (!template_url || template_url->suggestions_url().empty()) |
| 655 return NULL; | 657 return NULL; |
| 656 | 658 |
| 657 // Bail if the suggestion URL is invalid with the given replacements. | 659 // Bail if the suggestion URL is invalid with the given replacements. |
| 658 TemplateURLRef::SearchTermsArgs search_term_args(text); | 660 TemplateURLRef::SearchTermsArgs search_term_args(input.text()); |
| 659 search_term_args.cursor_position = input_.cursor_position(); | 661 search_term_args.cursor_position = input.cursor_position(); |
| 660 GURL suggest_url(template_url->suggestions_url_ref().ReplaceSearchTerms( | 662 GURL suggest_url(template_url->suggestions_url_ref().ReplaceSearchTerms( |
| 661 search_term_args)); | 663 search_term_args)); |
| 662 if (!suggest_url.is_valid()) | 664 if (!suggest_url.is_valid()) |
| 663 return NULL; | 665 return NULL; |
| 664 | 666 |
| 665 suggest_results_pending_++; | 667 suggest_results_pending_++; |
| 666 LogOmniboxSuggestRequest(REQUEST_SENT); | 668 LogOmniboxSuggestRequest(REQUEST_SENT); |
| 667 | 669 |
| 668 net::URLFetcher* fetcher = | 670 net::URLFetcher* fetcher = |
| 669 net::URLFetcher::Create(id, suggest_url, net::URLFetcher::GET, this); | 671 net::URLFetcher::Create(id, suggest_url, net::URLFetcher::GET, this); |
| 670 fetcher->SetRequestContext(profile_->GetRequestContext()); | 672 fetcher->SetRequestContext(profile_->GetRequestContext()); |
| 671 fetcher->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES); | 673 fetcher->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES); |
| 672 // Add Chrome experiment state to the request headers. | 674 // Add Chrome experiment state to the request headers. |
| 673 net::HttpRequestHeaders headers; | 675 net::HttpRequestHeaders headers; |
| 674 chrome_variations::VariationsHttpHeaderProvider::GetInstance()->AppendHeaders( | 676 chrome_variations::VariationsHttpHeaderProvider::GetInstance()->AppendHeaders( |
| 675 fetcher->GetOriginalURL(), profile_->IsOffTheRecord(), false, &headers); | 677 fetcher->GetOriginalURL(), profile_->IsOffTheRecord(), false, &headers); |
| 676 fetcher->SetExtraRequestHeaders(headers.ToString()); | 678 fetcher->SetExtraRequestHeaders(headers.ToString()); |
| 677 fetcher->Start(); | 679 fetcher->Start(); |
| 678 return fetcher; | 680 return fetcher; |
| 679 } | 681 } |
| 680 | 682 |
| 681 bool SearchProvider::ParseSuggestResults(Value* root_val, bool is_keyword) { | 683 bool SearchProvider::ParseSuggestResults(Value* root_val, bool is_keyword) { |
| 682 // TODO(pkasting): Fix |have_suggest_results_|; see http://crbug.com/130631 | 684 // TODO(pkasting): Fix |have_suggest_results_|; see http://crbug.com/130631 |
| 683 have_suggest_results_ = false; | 685 have_suggest_results_ = false; |
| 684 | 686 |
| 685 string16 query; | 687 string16 query; |
| 686 ListValue* root_list = NULL; | 688 ListValue* root_list = NULL; |
| 687 ListValue* results = NULL; | 689 ListValue* results = NULL; |
| 688 const string16& input_text = is_keyword ? keyword_input_text_ : input_.text(); | 690 const string16& input_text = |
| 691 is_keyword ? keyword_input_.text() : input_.text(); |
| 689 if (!root_val->GetAsList(&root_list) || !root_list->GetString(0, &query) || | 692 if (!root_val->GetAsList(&root_list) || !root_list->GetString(0, &query) || |
| 690 (query != input_text) || !root_list->GetList(1, &results)) | 693 (query != input_text) || !root_list->GetList(1, &results)) |
| 691 return false; | 694 return false; |
| 692 | 695 |
| 693 // 3rd element: Description list. | 696 // 3rd element: Description list. |
| 694 ListValue* descriptions = NULL; | 697 ListValue* descriptions = NULL; |
| 695 root_list->GetList(2, &descriptions); | 698 root_list->GetList(2, &descriptions); |
| 696 | 699 |
| 697 // 4th element: Disregard the query URL list for now. | 700 // 4th element: Disregard the query URL list for now. |
| 698 | 701 |
| (...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 943 | 946 |
| 944 void SearchProvider::AddHistoryResultsToMap(const HistoryResults& results, | 947 void SearchProvider::AddHistoryResultsToMap(const HistoryResults& results, |
| 945 bool is_keyword, | 948 bool is_keyword, |
| 946 int did_not_accept_suggestion, | 949 int did_not_accept_suggestion, |
| 947 MatchMap* map) { | 950 MatchMap* map) { |
| 948 if (results.empty()) | 951 if (results.empty()) |
| 949 return; | 952 return; |
| 950 | 953 |
| 951 bool prevent_inline_autocomplete = input_.prevent_inline_autocomplete() || | 954 bool prevent_inline_autocomplete = input_.prevent_inline_autocomplete() || |
| 952 (input_.type() == AutocompleteInput::URL); | 955 (input_.type() == AutocompleteInput::URL); |
| 953 const string16& input_text = is_keyword ? keyword_input_text_ : input_.text(); | 956 const string16& input_text = |
| 957 is_keyword ? keyword_input_.text() : input_.text(); |
| 954 bool input_multiple_words = HasMultipleWords(input_text); | 958 bool input_multiple_words = HasMultipleWords(input_text); |
| 955 | 959 |
| 956 SuggestResults scored_results; | 960 SuggestResults scored_results; |
| 957 if (!prevent_inline_autocomplete && input_multiple_words) { | 961 if (!prevent_inline_autocomplete && input_multiple_words) { |
| 958 // ScoreHistoryResults() allows autocompletion of multi-word, 1-visit | 962 // ScoreHistoryResults() allows autocompletion of multi-word, 1-visit |
| 959 // queries if the input also has multiple words. But if we were already | 963 // queries if the input also has multiple words. But if we were already |
| 960 // autocompleting a multi-word, multi-visit query, and the current input is | 964 // autocompleting a multi-word, multi-visit query, and the current input is |
| 961 // still a prefix of it, then changing the autocompletion suddenly feels | 965 // still a prefix of it, then changing the autocompletion suddenly feels |
| 962 // wrong. To detect this case, first score as if only one word has been | 966 // wrong. To detect this case, first score as if only one word has been |
| 963 // typed, then check for a best result that is an autocompleted, multi-word | 967 // 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... |
| 1036 i->set_relevance(last_relevance - 1); | 1040 i->set_relevance(last_relevance - 1); |
| 1037 last_relevance = i->relevance(); | 1041 last_relevance = i->relevance(); |
| 1038 } | 1042 } |
| 1039 | 1043 |
| 1040 return scored_results; | 1044 return scored_results; |
| 1041 } | 1045 } |
| 1042 | 1046 |
| 1043 void SearchProvider::AddSuggestResultsToMap(const SuggestResults& results, | 1047 void SearchProvider::AddSuggestResultsToMap(const SuggestResults& results, |
| 1044 bool is_keyword, | 1048 bool is_keyword, |
| 1045 MatchMap* map) { | 1049 MatchMap* map) { |
| 1046 const string16& input_text = is_keyword ? keyword_input_text_ : input_.text(); | 1050 const string16& input_text = |
| 1051 is_keyword ? keyword_input_.text() : input_.text(); |
| 1047 for (size_t i = 0; i < results.size(); ++i) { | 1052 for (size_t i = 0; i < results.size(); ++i) { |
| 1048 AddMatchToMap(results[i].suggestion(), input_text, results[i].relevance(), | 1053 AddMatchToMap(results[i].suggestion(), input_text, results[i].relevance(), |
| 1049 AutocompleteMatch::SEARCH_SUGGEST, i, is_keyword, map); | 1054 AutocompleteMatch::SEARCH_SUGGEST, i, is_keyword, map); |
| 1050 } | 1055 } |
| 1051 } | 1056 } |
| 1052 | 1057 |
| 1053 int SearchProvider::GetVerbatimRelevance() const { | 1058 int SearchProvider::GetVerbatimRelevance() const { |
| 1054 // Use the suggested verbatim relevance score if it is non-negative (valid), | 1059 // Use the suggested verbatim relevance score if it is non-negative (valid), |
| 1055 // if inline autocomplete isn't prevented (always show verbatim on backspace), | 1060 // if inline autocomplete isn't prevented (always show verbatim on backspace), |
| 1056 // and if it won't suppress verbatim, leaving no default provider matches. | 1061 // 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... |
| 1234 // results sorted by recency, this means we'll pick the most recent such | 1239 // results sorted by recency, this means we'll pick the most recent such |
| 1235 // result even if the precision of our relevance score is too low to | 1240 // result even if the precision of our relevance score is too low to |
| 1236 // distinguish the two. | 1241 // distinguish the two. |
| 1237 if (!i.second && (match.relevance > i.first->second.relevance)) | 1242 if (!i.second && (match.relevance > i.first->second.relevance)) |
| 1238 i.first->second = match; | 1243 i.first->second = match; |
| 1239 } | 1244 } |
| 1240 | 1245 |
| 1241 AutocompleteMatch SearchProvider::NavigationToMatch( | 1246 AutocompleteMatch SearchProvider::NavigationToMatch( |
| 1242 const NavigationResult& navigation, | 1247 const NavigationResult& navigation, |
| 1243 bool is_keyword) { | 1248 bool is_keyword) { |
| 1244 const string16& input = is_keyword ? keyword_input_text_ : input_.text(); | 1249 const string16& input = is_keyword ? keyword_input_.text() : input_.text(); |
| 1245 AutocompleteMatch match(this, navigation.relevance(), false, | 1250 AutocompleteMatch match(this, navigation.relevance(), false, |
| 1246 AutocompleteMatch::NAVSUGGEST); | 1251 AutocompleteMatch::NAVSUGGEST); |
| 1247 match.destination_url = navigation.url(); | 1252 match.destination_url = navigation.url(); |
| 1248 | 1253 |
| 1249 // First look for the user's input inside the fill_into_edit as it would be | 1254 // First look for the user's input inside the fill_into_edit as it would be |
| 1250 // without trimming the scheme, so we can find matches at the beginning of the | 1255 // without trimming the scheme, so we can find matches at the beginning of the |
| 1251 // scheme. | 1256 // scheme. |
| 1252 const string16 untrimmed_fill_into_edit( | 1257 const string16 untrimmed_fill_into_edit( |
| 1253 AutocompleteInput::FormattedStringWithEquivalentMeaning(navigation.url(), | 1258 AutocompleteInput::FormattedStringWithEquivalentMeaning(navigation.url(), |
| 1254 StringForURLDisplay(navigation.url(), true, false))); | 1259 StringForURLDisplay(navigation.url(), true, false))); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1301 } | 1306 } |
| 1302 | 1307 |
| 1303 void SearchProvider::UpdateDone() { | 1308 void SearchProvider::UpdateDone() { |
| 1304 // We're done when the timer isn't running, there are no suggest queries | 1309 // We're done when the timer isn't running, there are no suggest queries |
| 1305 // pending, and we're not waiting on instant. | 1310 // pending, and we're not waiting on instant. |
| 1306 done_ = (!timer_.IsRunning() && (suggest_results_pending_ == 0) && | 1311 done_ = (!timer_.IsRunning() && (suggest_results_pending_ == 0) && |
| 1307 (instant_finalized_ || | 1312 (instant_finalized_ || |
| 1308 (!chrome::BrowserInstantController::IsInstantEnabled(profile_) && | 1313 (!chrome::BrowserInstantController::IsInstantEnabled(profile_) && |
| 1309 !chrome::search::IsInstantExtendedAPIEnabled(profile_)))); | 1314 !chrome::search::IsInstantExtendedAPIEnabled(profile_)))); |
| 1310 } | 1315 } |
| OLD | NEW |