Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 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 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 83 // static | 83 // static |
| 84 const int SearchProvider::kDefaultProviderURLFetcherID = 1; | 84 const int SearchProvider::kDefaultProviderURLFetcherID = 1; |
| 85 // static | 85 // static |
| 86 const int SearchProvider::kKeywordProviderURLFetcherID = 2; | 86 const int SearchProvider::kKeywordProviderURLFetcherID = 2; |
| 87 // static | 87 // static |
| 88 bool SearchProvider::query_suggest_immediately_ = false; | 88 bool SearchProvider::query_suggest_immediately_ = false; |
| 89 | 89 |
| 90 SearchProvider::SearchProvider(ACProviderListener* listener, Profile* profile) | 90 SearchProvider::SearchProvider(ACProviderListener* listener, Profile* profile) |
| 91 : AutocompleteProvider(listener, profile, "Search"), | 91 : AutocompleteProvider(listener, profile, "Search"), |
| 92 providers_(profile), | 92 providers_(profile), |
| 93 has_verbatim_relevance_(false), | |
| 94 verbatim_relevance_(0), | |
| 93 suggest_results_pending_(0), | 95 suggest_results_pending_(0), |
| 94 have_suggest_results_(false), | 96 have_suggest_results_(false), |
| 95 instant_finalized_(false) { | 97 instant_finalized_(false) { |
| 96 // We use GetSuggestNumberOfGroups() as the group ID to mean "not in field | 98 // We use GetSuggestNumberOfGroups() as the group ID to mean "not in field |
| 97 // trial." Field trial groups run from 0 to GetSuggestNumberOfGroups() - 1 | 99 // trial." Field trial groups run from 0 to GetSuggestNumberOfGroups() - 1 |
| 98 // (inclusive). | 100 // (inclusive). |
| 99 int suggest_field_trial_group_number = | 101 int suggest_field_trial_group_number = |
| 100 AutocompleteFieldTrial::GetSuggestNumberOfGroups(); | 102 AutocompleteFieldTrial::GetSuggestNumberOfGroups(); |
| 101 if (AutocompleteFieldTrial::InSuggestFieldTrial()) { | 103 if (AutocompleteFieldTrial::InSuggestFieldTrial()) { |
| 102 suggest_field_trial_group_number = | 104 suggest_field_trial_group_number = |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 140 for (ACMatches::iterator i = matches_.begin(); i != matches_.end();) { | 142 for (ACMatches::iterator i = matches_.begin(); i != matches_.end();) { |
| 141 if (((i->type == AutocompleteMatch::SEARCH_HISTORY) || | 143 if (((i->type == AutocompleteMatch::SEARCH_HISTORY) || |
| 142 (i->type == AutocompleteMatch::SEARCH_SUGGEST)) && | 144 (i->type == AutocompleteMatch::SEARCH_SUGGEST)) && |
| 143 (i->fill_into_edit == text)) { | 145 (i->fill_into_edit == text)) { |
| 144 i = matches_.erase(i); | 146 i = matches_.erase(i); |
| 145 } else { | 147 } else { |
| 146 ++i; | 148 ++i; |
| 147 } | 149 } |
| 148 } | 150 } |
| 149 | 151 |
| 152 // TODO(msw): Ensure the experiments don't interfere with instant... | |
| 150 // Add the new suggest result. We give it a rank higher than | 153 // Add the new suggest result. We give it a rank higher than |
| 151 // SEARCH_WHAT_YOU_TYPED so that it gets autocompleted. | 154 // SEARCH_WHAT_YOU_TYPED so that it gets autocompleted. |
| 152 int did_not_accept_default_suggestion = default_suggest_results_.empty() ? | 155 int did_not_accept_default_suggestion = default_suggest_results_.empty() ? |
| 153 TemplateURLRef::NO_SUGGESTIONS_AVAILABLE : | 156 TemplateURLRef::NO_SUGGESTIONS_AVAILABLE : |
| 154 TemplateURLRef::NO_SUGGESTION_CHOSEN; | 157 TemplateURLRef::NO_SUGGESTION_CHOSEN; |
| 155 MatchMap match_map; | 158 MatchMap match_map; |
| 156 AddMatchToMap(text, adjusted_input_text, | 159 AddMatchToMap(text, adjusted_input_text, |
| 157 CalculateRelevanceForWhatYouTyped() + 1, | 160 CalculateRelevanceForWhatYouTyped() + 1, |
| 158 AutocompleteMatch::SEARCH_SUGGEST, | 161 AutocompleteMatch::SEARCH_SUGGEST, |
| 159 did_not_accept_default_suggestion, false, | 162 did_not_accept_default_suggestion, false, |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 227 return; | 230 return; |
| 228 } | 231 } |
| 229 | 232 |
| 230 input_ = input; | 233 input_ = input; |
| 231 | 234 |
| 232 DoHistoryQuery(minimal_changes); | 235 DoHistoryQuery(minimal_changes); |
| 233 StartOrStopSuggestQuery(minimal_changes); | 236 StartOrStopSuggestQuery(minimal_changes); |
| 234 ConvertResultsToAutocompleteMatches(); | 237 ConvertResultsToAutocompleteMatches(); |
| 235 } | 238 } |
| 236 | 239 |
| 240 SearchProvider::SuggestResult::SuggestResult(const string16& suggestion, | |
| 241 bool has_suggested_relevance, | |
| 242 int relevance) | |
| 243 : suggestion(suggestion), | |
| 244 has_suggested_relevance(has_suggested_relevance), | |
| 245 relevance(relevance) { | |
| 246 } | |
| 247 | |
| 248 SearchProvider::NavigationResult::NavigationResult( | |
| 249 const GURL& url, | |
| 250 const string16& site_name, | |
| 251 bool has_suggested_relevance, | |
| 252 int relevance) | |
| 253 : url(url), | |
| 254 site_name(site_name), | |
| 255 has_suggested_relevance(has_suggested_relevance), | |
| 256 relevance(relevance) { | |
| 257 } | |
| 258 | |
| 237 class SearchProvider::CompareScoredTerms { | 259 class SearchProvider::CompareScoredTerms { |
| 238 public: | 260 public: |
| 239 bool operator()(const ScoredTerm& a, const ScoredTerm& b) { | 261 bool operator()(const ScoredTerm& a, const ScoredTerm& b) { |
| 240 // Sort in descending relevance order. | 262 // Sort in descending relevance order. |
| 241 return a.second > b.second; | 263 return a.second > b.second; |
| 242 } | 264 } |
| 243 }; | 265 }; |
| 244 | 266 |
| 245 void SearchProvider::Run() { | 267 void SearchProvider::Run() { |
| 246 // Start a new request with the current input. | 268 // Start a new request with the current input. |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 349 keyword_input_text_, num_matches, &keyword_history_results_); | 371 keyword_input_text_, num_matches, &keyword_history_results_); |
| 350 } | 372 } |
| 351 } | 373 } |
| 352 | 374 |
| 353 void SearchProvider::StartOrStopSuggestQuery(bool minimal_changes) { | 375 void SearchProvider::StartOrStopSuggestQuery(bool minimal_changes) { |
| 354 // Don't send any queries to the server until some time has elapsed after | 376 // Don't send any queries to the server until some time has elapsed after |
| 355 // the last keypress, to avoid flooding the server with requests we are | 377 // the last keypress, to avoid flooding the server with requests we are |
| 356 // likely to end up throwing away anyway. | 378 // likely to end up throwing away anyway. |
| 357 const int kQueryDelayMs = 200; | 379 const int kQueryDelayMs = 200; |
| 358 | 380 |
| 381 // TODO(msw): Synchronously remove irrelevant inline-autocomplete *results*... | |
| 382 | |
| 359 if (!IsQuerySuitableForSuggest()) { | 383 if (!IsQuerySuitableForSuggest()) { |
| 360 StopSuggest(); | 384 StopSuggest(); |
| 385 ClearResults(); | |
| 361 return; | 386 return; |
| 362 } | 387 } |
| 363 | 388 |
| 364 // For the minimal_changes case, if we finished the previous query and still | 389 // For the minimal_changes case, if we finished the previous query and still |
| 365 // have its results, or are allowed to keep running it, just do that, rather | 390 // have its results, or are allowed to keep running it, just do that, rather |
| 366 // than starting a new query. | 391 // than starting a new query. |
| 367 if (minimal_changes && | 392 if (minimal_changes && |
| 368 (have_suggest_results_ || | 393 (have_suggest_results_ || |
| 369 (!done_ && | 394 (!done_ && |
| 370 input_.matches_requested() == AutocompleteInput::ALL_MATCHES))) | 395 input_.matches_requested() == AutocompleteInput::ALL_MATCHES))) |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 442 | 467 |
| 443 return true; | 468 return true; |
| 444 } | 469 } |
| 445 | 470 |
| 446 void SearchProvider::StopSuggest() { | 471 void SearchProvider::StopSuggest() { |
| 447 suggest_results_pending_ = 0; | 472 suggest_results_pending_ = 0; |
| 448 timer_.Stop(); | 473 timer_.Stop(); |
| 449 // Stop any in-progress URL fetches. | 474 // Stop any in-progress URL fetches. |
| 450 keyword_fetcher_.reset(); | 475 keyword_fetcher_.reset(); |
| 451 default_fetcher_.reset(); | 476 default_fetcher_.reset(); |
| 477 } | |
| 478 | |
| 479 void SearchProvider::ClearResults() { | |
| 452 keyword_suggest_results_.clear(); | 480 keyword_suggest_results_.clear(); |
| 453 default_suggest_results_.clear(); | 481 default_suggest_results_.clear(); |
| 454 keyword_navigation_results_.clear(); | 482 keyword_navigation_results_.clear(); |
| 455 default_navigation_results_.clear(); | 483 default_navigation_results_.clear(); |
| 456 have_suggest_results_ = false; | 484 have_suggest_results_ = false; |
| 457 } | 485 } |
| 458 | 486 |
| 459 content::URLFetcher* SearchProvider::CreateSuggestFetcher( | 487 content::URLFetcher* SearchProvider::CreateSuggestFetcher( |
| 460 int id, | 488 int id, |
| 461 const TemplateURLRef& suggestions_url, | 489 const TemplateURLRef& suggestions_url, |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 472 } | 500 } |
| 473 | 501 |
| 474 bool SearchProvider::ParseSuggestResults(Value* root_val, | 502 bool SearchProvider::ParseSuggestResults(Value* root_val, |
| 475 bool is_keyword, | 503 bool is_keyword, |
| 476 const string16& input_text, | 504 const string16& input_text, |
| 477 SuggestResults* suggest_results) { | 505 SuggestResults* suggest_results) { |
| 478 if (!root_val->IsType(Value::TYPE_LIST)) | 506 if (!root_val->IsType(Value::TYPE_LIST)) |
| 479 return false; | 507 return false; |
| 480 ListValue* root_list = static_cast<ListValue*>(root_val); | 508 ListValue* root_list = static_cast<ListValue*>(root_val); |
| 481 | 509 |
| 482 Value* query_val; | |
| 483 string16 query_str; | 510 string16 query_str; |
| 484 Value* result_val; | 511 ListValue* result_list = NULL; |
| 485 if ((root_list->GetSize() < 2) || !root_list->Get(0, &query_val) || | 512 if ((root_list->GetSize() < 2) || !root_list->GetString(0, &query_str) || |
| 486 !query_val->GetAsString(&query_str) || | 513 (query_str != input_text) || !root_list->GetList(1, &result_list)) |
| 487 (query_str != input_text) || | |
| 488 !root_list->Get(1, &result_val) || !result_val->IsType(Value::TYPE_LIST)) | |
| 489 return false; | 514 return false; |
| 490 | 515 |
| 516 // 3rd element: Description list. | |
| 491 ListValue* description_list = NULL; | 517 ListValue* description_list = NULL; |
| 492 if (root_list->GetSize() > 2) { | 518 if (root_list->GetSize() > 2) |
| 493 // 3rd element: Description list. | 519 root_list->GetList(2, &description_list); |
| 494 Value* description_val; | 520 |
| 495 if (root_list->Get(2, &description_val) && | 521 // 4th element: Disregard the query URL list for now. |
| 496 description_val->IsType(Value::TYPE_LIST)) | 522 |
| 497 description_list = static_cast<ListValue*>(description_val); | 523 // 5th element: Optional key-value pairs from the Suggest server. |
| 524 DictionaryValue* dict_val = NULL; | |
| 525 ListValue* type_list = NULL; | |
| 526 ListValue* relevance_list = NULL; | |
| 527 has_verbatim_relevance_ = false; | |
| 528 verbatim_relevance_ = 0; | |
| 529 if (root_list->GetSize() > 4 && root_list->GetDictionary(4, &dict_val)) { | |
| 530 // Parse Google Suggest specific type extension. | |
| 531 const std::string kGoogleSuggestType("google:suggesttype"); | |
| 532 dict_val->GetList(kGoogleSuggestType, &type_list); | |
| 533 | |
| 534 // Parse Google Suggest specific relevance extension. | |
| 535 const std::string kGoogleSuggestRelevance("google:suggestrelevance"); | |
| 536 dict_val->GetList(kGoogleSuggestRelevance, &relevance_list); | |
| 537 | |
| 538 // Parse Google Suggest specific verbatim relevance extension. | |
| 539 const std::string kGoogleVerbatimRelevance("google:verbatimrelevance"); | |
| 540 if (dict_val->GetInteger(kGoogleVerbatimRelevance, &verbatim_relevance_)) | |
| 541 has_verbatim_relevance_ = true; | |
| 498 } | 542 } |
| 499 | 543 |
| 500 // We don't care about the query URL list (the fourth element in the | 544 // Clear the previous results if new results are available. |
| 501 // response) for now. | 545 if (result_list->GetSize() > 0) |
| 546 ClearResults(); | |
| 502 | 547 |
| 503 // Parse optional data in the results from the Suggest server if any. | |
| 504 ListValue* type_list = NULL; | |
| 505 // 5th argument: Optional key-value pairs. | |
| 506 // TODO: We may iterate the 5th+ arguments of the root_list if any other | |
| 507 // optional data are defined. | |
| 508 if (root_list->GetSize() > 4) { | |
| 509 Value* optional_val; | |
| 510 if (root_list->Get(4, &optional_val) && | |
| 511 optional_val->IsType(Value::TYPE_DICTIONARY)) { | |
| 512 DictionaryValue* dict_val = static_cast<DictionaryValue*>(optional_val); | |
| 513 | |
| 514 // Parse Google Suggest specific type extension. | |
| 515 const std::string kGoogleSuggestType("google:suggesttype"); | |
| 516 if (dict_val->HasKey(kGoogleSuggestType)) | |
| 517 dict_val->GetList(kGoogleSuggestType, &type_list); | |
| 518 } | |
| 519 } | |
| 520 | |
| 521 ListValue* result_list = static_cast<ListValue*>(result_val); | |
| 522 for (size_t i = 0; i < result_list->GetSize(); ++i) { | 548 for (size_t i = 0; i < result_list->GetSize(); ++i) { |
| 523 Value* suggestion_val; | |
| 524 string16 suggestion_str; | 549 string16 suggestion_str; |
| 525 if (!result_list->Get(i, &suggestion_val) || | 550 if (!result_list->GetString(i, &suggestion_str)) |
| 526 !suggestion_val->GetAsString(&suggestion_str)) | |
| 527 return false; | 551 return false; |
| 528 | 552 |
| 529 // Google search may return empty suggestions for weird input characters, | 553 // Google search may return empty suggestions for weird input characters, |
| 530 // they make no sense at all and can cause problem in our code. | 554 // they make no sense at all and can cause problem in our code. |
| 531 // See http://crbug.com/56214 | 555 // See http://crbug.com/56214 |
| 532 if (!suggestion_str.length()) | 556 if (!suggestion_str.length()) |
| 533 continue; | 557 continue; |
| 534 | 558 |
| 535 Value* type_val; | 559 bool has_suggested_relevance = false; |
| 536 std::string type_str; | 560 int relevance = 0; |
| 537 if (type_list && type_list->Get(i, &type_val) && | 561 if (relevance_list && relevance_list->GetInteger(i, &relevance)) |
| 538 type_val->GetAsString(&type_str) && (type_str == "NAVIGATION")) { | 562 has_suggested_relevance = true; |
| 539 Value* site_val; | 563 |
| 564 std::string type; | |
| 565 if (type_list && type_list->GetString(i, &type) && (type == "NAVIGATION")) { | |
| 540 string16 site_name; | 566 string16 site_name; |
| 541 NavigationResults& navigation_results = | 567 NavigationResults& navigation_results = |
| 542 is_keyword ? keyword_navigation_results_ : | 568 is_keyword ? keyword_navigation_results_ : |
| 543 default_navigation_results_; | 569 default_navigation_results_; |
| 544 if ((navigation_results.size() < kMaxMatches) && | 570 if ((navigation_results.size() < kMaxMatches) && |
| 545 description_list && description_list->Get(i, &site_val) && | 571 description_list && description_list->GetString(i, &site_name)) { |
| 546 site_val->IsType(Value::TYPE_STRING) && | |
| 547 site_val->GetAsString(&site_name)) { | |
| 548 // We can't blindly trust the URL coming from the server to be valid. | 572 // We can't blindly trust the URL coming from the server to be valid. |
| 549 GURL result_url(URLFixerUpper::FixupURL(UTF16ToUTF8(suggestion_str), | 573 GURL result_url(URLFixerUpper::FixupURL(UTF16ToUTF8(suggestion_str), |
| 550 std::string())); | 574 std::string())); |
| 551 if (result_url.is_valid()) { | 575 if (result_url.is_valid()) { |
| 552 navigation_results.push_back(NavigationResult(result_url, site_name)); | 576 navigation_results.push_back(NavigationResult(result_url, site_name, |
| 577 has_suggested_relevance, | |
| 578 relevance)); | |
| 553 } | 579 } |
| 554 } | 580 } |
| 555 } else { | 581 } else { |
| 556 // TODO(kochi): Currently we treat a calculator result as a query, but it | 582 // TODO(kochi): Currently we treat a calculator result as a query, but it |
| 557 // is better to have better presentation for caluculator results. | 583 // is better to have better presentation for caluculator results. |
| 558 if (suggest_results->size() < kMaxMatches) | 584 if (suggest_results->size() < kMaxMatches) { |
| 559 suggest_results->push_back(suggestion_str); | 585 suggest_results->push_back(SuggestResult(suggestion_str, |
| 586 has_suggested_relevance, | |
| 587 relevance)); | |
| 588 } | |
| 560 } | 589 } |
| 561 } | 590 } |
| 562 | 591 |
| 563 return true; | 592 return true; |
| 564 } | 593 } |
| 565 | 594 |
| 566 void SearchProvider::ConvertResultsToAutocompleteMatches() { | 595 void SearchProvider::ConvertResultsToAutocompleteMatches() { |
| 567 // Convert all the results to matches and add them to a map, so we can keep | 596 // Convert all the results to matches and add them to a map, so we can keep |
| 568 // the most relevant match for each result. | 597 // the most relevant match for each result. |
| 569 MatchMap map; | 598 MatchMap map; |
| 570 const Time no_time; | 599 const Time no_time; |
| 571 int did_not_accept_keyword_suggestion = keyword_suggest_results_.empty() ? | 600 int did_not_accept_keyword_suggestion = keyword_suggest_results_.empty() ? |
| 572 TemplateURLRef::NO_SUGGESTIONS_AVAILABLE : | 601 TemplateURLRef::NO_SUGGESTIONS_AVAILABLE : |
| 573 TemplateURLRef::NO_SUGGESTION_CHOSEN; | 602 TemplateURLRef::NO_SUGGESTION_CHOSEN; |
| 574 // Keyword what you typed results are handled by the KeywordProvider. | 603 // Keyword what you typed results are handled by the KeywordProvider. |
| 575 | 604 |
| 605 // TODO(msw): Use normal scoring, disable experiments for instant? | |
| 606 int verbatim_relevance = CalculateRelevanceForWhatYouTyped(); | |
| 607 bool add_verbatim_result = verbatim_relevance > 0; | |
| 608 | |
| 576 int did_not_accept_default_suggestion = default_suggest_results_.empty() ? | 609 int did_not_accept_default_suggestion = default_suggest_results_.empty() ? |
| 577 TemplateURLRef::NO_SUGGESTIONS_AVAILABLE : | 610 TemplateURLRef::NO_SUGGESTIONS_AVAILABLE : |
| 578 TemplateURLRef::NO_SUGGESTION_CHOSEN; | 611 TemplateURLRef::NO_SUGGESTION_CHOSEN; |
| 579 if (providers_.valid_default_provider()) { | 612 if (providers_.valid_default_provider() && add_verbatim_result) { |
| 580 AddMatchToMap(input_.text(), input_.text(), | 613 AddMatchToMap(input_.text(), input_.text(), verbatim_relevance, |
| 581 CalculateRelevanceForWhatYouTyped(), | |
| 582 AutocompleteMatch::SEARCH_WHAT_YOU_TYPED, | 614 AutocompleteMatch::SEARCH_WHAT_YOU_TYPED, |
| 583 did_not_accept_default_suggestion, false, | 615 did_not_accept_default_suggestion, false, |
| 584 input_.prevent_inline_autocomplete(), &map); | 616 input_.prevent_inline_autocomplete(), &map); |
| 585 if (!default_provider_suggest_text_.empty()) { | 617 if (!default_provider_suggest_text_.empty()) { |
| 586 AddMatchToMap(input_.text() + default_provider_suggest_text_, | 618 AddMatchToMap(input_.text() + default_provider_suggest_text_, |
| 587 input_.text(), CalculateRelevanceForWhatYouTyped() + 1, | 619 input_.text(), verbatim_relevance + 1, |
| 588 AutocompleteMatch::SEARCH_SUGGEST, | 620 AutocompleteMatch::SEARCH_SUGGEST, |
| 589 did_not_accept_default_suggestion, false, | 621 did_not_accept_default_suggestion, false, |
| 590 input_.prevent_inline_autocomplete(), &map); | 622 input_.prevent_inline_autocomplete(), &map); |
| 591 } | 623 } |
| 592 } | 624 } |
| 593 | 625 |
| 594 AddHistoryResultsToMap(keyword_history_results_, true, | 626 AddHistoryResultsToMap(keyword_history_results_, true, |
| 595 did_not_accept_keyword_suggestion, &map); | 627 did_not_accept_keyword_suggestion, &map); |
| 596 AddHistoryResultsToMap(default_history_results_, false, | 628 AddHistoryResultsToMap(default_history_results_, false, |
| 597 did_not_accept_default_suggestion, &map); | 629 did_not_accept_default_suggestion, &map); |
| 598 | 630 |
| 599 AddSuggestResultsToMap(keyword_suggest_results_, true, | 631 AddSuggestResultsToMap(keyword_suggest_results_, true, |
| 600 did_not_accept_keyword_suggestion, &map); | 632 did_not_accept_keyword_suggestion, &map); |
| 601 AddSuggestResultsToMap(default_suggest_results_, false, | 633 AddSuggestResultsToMap(default_suggest_results_, false, |
| 602 did_not_accept_default_suggestion, &map); | 634 did_not_accept_default_suggestion, &map); |
| 603 | 635 |
| 604 // Now add the most relevant matches from the map to |matches_|. | 636 // Now add the most relevant matches from the map to |matches_|. |
| 605 matches_.clear(); | 637 matches_.clear(); |
| 606 for (MatchMap::const_iterator i(map.begin()); i != map.end(); ++i) | 638 for (MatchMap::const_iterator i(map.begin()); i != map.end(); ++i) |
| 607 matches_.push_back(i->second); | 639 matches_.push_back(i->second); |
| 608 | 640 |
| 609 AddNavigationResultsToMatches(keyword_navigation_results_, true); | 641 AddNavigationResultsToMatches(keyword_navigation_results_, true); |
| 610 AddNavigationResultsToMatches(default_navigation_results_, false); | 642 AddNavigationResultsToMatches(default_navigation_results_, false); |
| 611 | 643 |
| 612 const size_t max_total_matches = kMaxMatches + 1; // 1 for "what you typed" | 644 // Allow an additional match for "what you typed", if it's used. |
| 645 const size_t max_total_matches = kMaxMatches + (add_verbatim_result ? 0 : 1); | |
|
Mark P
2012/05/04 20:31:38
Are the 1s and 0s backward here?
msw
2012/05/04 22:13:39
Done.
| |
| 613 std::partial_sort(matches_.begin(), | 646 std::partial_sort(matches_.begin(), |
| 614 matches_.begin() + std::min(max_total_matches, matches_.size()), | 647 matches_.begin() + std::min(max_total_matches, matches_.size()), |
| 615 matches_.end(), &AutocompleteMatch::MoreRelevant); | 648 matches_.end(), &AutocompleteMatch::MoreRelevant); |
| 616 if (matches_.size() > max_total_matches) | 649 if (matches_.size() > max_total_matches) |
| 617 matches_.erase(matches_.begin() + max_total_matches, matches_.end()); | 650 matches_.erase(matches_.begin() + max_total_matches, matches_.end()); |
| 618 | 651 |
| 619 UpdateStarredStateOfMatches(); | 652 UpdateStarredStateOfMatches(); |
| 620 | |
| 621 UpdateDone(); | 653 UpdateDone(); |
| 622 } | 654 } |
| 623 | 655 |
| 624 void SearchProvider::AddNavigationResultsToMatches( | 656 void SearchProvider::AddNavigationResultsToMatches( |
| 625 const NavigationResults& navigation_results, | 657 const NavigationResults& navigation_results, |
| 626 bool is_keyword) { | 658 bool is_keyword) { |
| 627 if (!navigation_results.empty()) { | 659 if (!navigation_results.empty()) { |
| 628 // TODO(kochi): http://b/1170574 We add only one results for navigational | 660 // TODO(kochi): http://b/1170574 We add only one results for navigational |
| 629 // suggestions. If we can get more useful information about the score, | 661 // suggestions. If we can get more useful information about the score, |
| 630 // consider adding more results. | 662 // consider adding more results. |
| 631 const size_t num_results = is_keyword ? | |
| 632 keyword_navigation_results_.size() : default_navigation_results_.size(); | |
| 633 matches_.push_back(NavigationToMatch(navigation_results.front(), | 663 matches_.push_back(NavigationToMatch(navigation_results.front(), |
| 634 CalculateRelevanceForNavigation(num_results, 0, is_keyword), | 664 CalculateRelevanceForNavigation(navigation_results, 0, is_keyword), |
| 635 is_keyword)); | 665 is_keyword)); |
| 636 } | 666 } |
| 637 } | 667 } |
| 638 | 668 |
| 639 void SearchProvider::AddHistoryResultsToMap(const HistoryResults& results, | 669 void SearchProvider::AddHistoryResultsToMap(const HistoryResults& results, |
| 640 bool is_keyword, | 670 bool is_keyword, |
| 641 int did_not_accept_suggestion, | 671 int did_not_accept_suggestion, |
| 642 MatchMap* map) { | 672 MatchMap* map) { |
| 643 if (results.empty()) | 673 if (results.empty()) |
| 644 return; | 674 return; |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 734 | 764 |
| 735 return scored_terms; | 765 return scored_terms; |
| 736 } | 766 } |
| 737 | 767 |
| 738 void SearchProvider::AddSuggestResultsToMap( | 768 void SearchProvider::AddSuggestResultsToMap( |
| 739 const SuggestResults& suggest_results, | 769 const SuggestResults& suggest_results, |
| 740 bool is_keyword, | 770 bool is_keyword, |
| 741 int did_not_accept_suggestion, | 771 int did_not_accept_suggestion, |
| 742 MatchMap* map) { | 772 MatchMap* map) { |
| 743 for (size_t i = 0; i < suggest_results.size(); ++i) { | 773 for (size_t i = 0; i < suggest_results.size(); ++i) { |
| 744 AddMatchToMap(suggest_results[i], | 774 AddMatchToMap(suggest_results[i].suggestion, |
| 745 is_keyword ? keyword_input_text_ : input_.text(), | 775 is_keyword ? keyword_input_text_ : input_.text(), |
| 746 CalculateRelevanceForSuggestion(suggest_results.size(), i, | 776 CalculateRelevanceForSuggestion(suggest_results, i, |
| 747 is_keyword), | 777 is_keyword), |
| 748 AutocompleteMatch::SEARCH_SUGGEST, | 778 AutocompleteMatch::SEARCH_SUGGEST, |
| 749 static_cast<int>(i), is_keyword, | 779 static_cast<int>(i), is_keyword, |
| 750 input_.prevent_inline_autocomplete(), map); | 780 input_.prevent_inline_autocomplete(), map); |
| 751 } | 781 } |
| 752 } | 782 } |
| 753 | 783 |
| 754 int SearchProvider::CalculateRelevanceForWhatYouTyped() const { | 784 int SearchProvider::CalculateRelevanceForWhatYouTyped() const { |
| 785 // TODO(msw): Effect SEARCH_WHAT_YOU_TYPED match (line 624) and instant?? | |
| 786 if (has_verbatim_relevance_ && !input_.prevent_inline_autocomplete()) | |
| 787 return verbatim_relevance_; | |
| 788 | |
| 755 if (providers_.valid_keyword_provider()) | 789 if (providers_.valid_keyword_provider()) |
| 756 return 250; | 790 return 250; |
| 757 | 791 |
| 758 switch (input_.type()) { | 792 switch (input_.type()) { |
| 759 case AutocompleteInput::UNKNOWN: | 793 case AutocompleteInput::UNKNOWN: |
| 760 case AutocompleteInput::QUERY: | 794 case AutocompleteInput::QUERY: |
| 761 case AutocompleteInput::FORCED_QUERY: | 795 case AutocompleteInput::FORCED_QUERY: |
| 762 return 1300; | 796 return 1300; |
| 763 | 797 |
| 764 case AutocompleteInput::REQUESTED_URL: | 798 case AutocompleteInput::REQUESTED_URL: |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 801 // Don't let scores go below 0. Negative relevance scores are meaningful in | 835 // Don't let scores go below 0. Negative relevance scores are meaningful in |
| 802 // a different way. | 836 // a different way. |
| 803 int base_score; | 837 int base_score; |
| 804 if (is_primary_provider) | 838 if (is_primary_provider) |
| 805 base_score = (input_.type() == AutocompleteInput::URL) ? 750 : 1050; | 839 base_score = (input_.type() == AutocompleteInput::URL) ? 750 : 1050; |
| 806 else | 840 else |
| 807 base_score = 200; | 841 base_score = 200; |
| 808 return std::max(0, base_score - score_discount); | 842 return std::max(0, base_score - score_discount); |
| 809 } | 843 } |
| 810 | 844 |
| 811 int SearchProvider::CalculateRelevanceForSuggestion(size_t num_results, | 845 int SearchProvider::CalculateRelevanceForSuggestion( |
| 812 size_t result_number, | 846 const SuggestResults& results, |
| 813 bool is_keyword) const { | 847 size_t result_number, |
| 814 DCHECK(result_number < num_results); | 848 bool is_keyword) const { |
| 849 DCHECK(result_number < results.size()); | |
| 850 if (results[result_number].has_suggested_relevance) | |
| 851 return results[result_number].relevance; | |
| 852 | |
| 815 int base_score; | 853 int base_score; |
| 816 if (!providers_.is_primary_provider(is_keyword)) | 854 if (!providers_.is_primary_provider(is_keyword)) |
| 817 base_score = 100; | 855 base_score = 100; |
| 818 else | 856 else |
| 819 base_score = (input_.type() == AutocompleteInput::URL) ? 300 : 600; | 857 base_score = (input_.type() == AutocompleteInput::URL) ? 300 : 600; |
| 820 return base_score + | 858 return base_score + |
| 821 static_cast<int>(num_results - 1 - result_number); | 859 static_cast<int>(results.size() - 1 - result_number); |
| 822 } | 860 } |
| 823 | 861 |
| 824 int SearchProvider::CalculateRelevanceForNavigation(size_t num_results, | 862 int SearchProvider::CalculateRelevanceForNavigation( |
| 825 size_t result_number, | 863 const NavigationResults& results, |
| 826 bool is_keyword) const { | 864 size_t result_number, |
| 827 DCHECK(result_number < num_results); | 865 bool is_keyword) const { |
| 828 // TODO(kochi): http://b/784900 Use relevance score from the NavSuggest | 866 DCHECK(result_number < results.size()); |
| 829 // server if possible. | 867 if (results[result_number].has_suggested_relevance) |
| 868 return results[result_number].relevance; | |
| 869 | |
| 830 return (providers_.is_primary_provider(is_keyword) ? 800 : 150) + | 870 return (providers_.is_primary_provider(is_keyword) ? 800 : 150) + |
| 831 static_cast<int>(num_results - 1 - result_number); | 871 static_cast<int>(results.size() - 1 - result_number); |
| 832 } | 872 } |
| 833 | 873 |
| 834 void SearchProvider::AddMatchToMap(const string16& query_string, | 874 void SearchProvider::AddMatchToMap(const string16& query_string, |
| 835 const string16& input_text, | 875 const string16& input_text, |
| 836 int relevance, | 876 int relevance, |
| 837 AutocompleteMatch::Type type, | 877 AutocompleteMatch::Type type, |
| 838 int accepted_suggestion, | 878 int accepted_suggestion, |
| 839 bool is_keyword, | 879 bool is_keyword, |
| 840 bool prevent_inline_autocomplete, | 880 bool prevent_inline_autocomplete, |
| 841 MatchMap* map) { | 881 MatchMap* map) { |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 952 &match.description_class); | 992 &match.description_class); |
| 953 | 993 |
| 954 // When the user forced a query, we need to make sure all the fill_into_edit | 994 // When the user forced a query, we need to make sure all the fill_into_edit |
| 955 // values preserve that property. Otherwise, if the user starts editing a | 995 // values preserve that property. Otherwise, if the user starts editing a |
| 956 // suggestion, non-Search results will suddenly appear. | 996 // suggestion, non-Search results will suddenly appear. |
| 957 if (input_.type() == AutocompleteInput::FORCED_QUERY) | 997 if (input_.type() == AutocompleteInput::FORCED_QUERY) |
| 958 match.fill_into_edit.assign(ASCIIToUTF16("?")); | 998 match.fill_into_edit.assign(ASCIIToUTF16("?")); |
| 959 match.fill_into_edit.append( | 999 match.fill_into_edit.append( |
| 960 AutocompleteInput::FormattedStringWithEquivalentMeaning(navigation.url, | 1000 AutocompleteInput::FormattedStringWithEquivalentMeaning(navigation.url, |
| 961 match.contents)); | 1001 match.contents)); |
| 962 // TODO(pkasting): http://b/1112879 These should perhaps be | 1002 // Inline-autocomplete NavigationResults; exclude AutocompleteInput::URL. |
| 963 // inline-autocompletable? | 1003 if (input_.type() != AutocompleteInput::URL && |
| 1004 !input_.prevent_inline_autocomplete()) { | |
| 1005 size_t start = match.fill_into_edit.find(input_text); | |
| 1006 if (start != string16::npos) | |
| 1007 match.inline_autocomplete_offset = start + input_text.length(); | |
| 1008 } | |
| 964 | 1009 |
| 965 return match; | 1010 return match; |
| 966 } | 1011 } |
| 967 | 1012 |
| 968 void SearchProvider::UpdateDone() { | 1013 void SearchProvider::UpdateDone() { |
| 969 // We're done when there are no more suggest queries pending (this is set to 1 | 1014 // We're done when there are no more suggest queries pending (this is set to 1 |
| 970 // when the timer is started) and we're not waiting on instant. | 1015 // when the timer is started) and we're not waiting on instant. |
| 971 done_ = ((suggest_results_pending_ == 0) && | 1016 done_ = ((suggest_results_pending_ == 0) && |
| 972 (instant_finalized_ || !InstantController::IsEnabled(profile_))); | 1017 (instant_finalized_ || !InstantController::IsEnabled(profile_))); |
| 973 } | 1018 } |
| OLD | NEW |