| 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 27 matching lines...) Expand all Loading... |
| 38 #include "chrome/browser/search_engines/template_url_service_factory.h" | 38 #include "chrome/browser/search_engines/template_url_service_factory.h" |
| 39 #include "chrome/browser/sync/profile_sync_service.h" | 39 #include "chrome/browser/sync/profile_sync_service.h" |
| 40 #include "chrome/browser/sync/profile_sync_service_factory.h" | 40 #include "chrome/browser/sync/profile_sync_service_factory.h" |
| 41 #include "chrome/browser/ui/browser.h" | 41 #include "chrome/browser/ui/browser.h" |
| 42 #include "chrome/browser/ui/browser_finder.h" | 42 #include "chrome/browser/ui/browser_finder.h" |
| 43 #include "chrome/browser/ui/browser_instant_controller.h" | 43 #include "chrome/browser/ui/browser_instant_controller.h" |
| 44 #include "chrome/browser/ui/search/instant_controller.h" | 44 #include "chrome/browser/ui/search/instant_controller.h" |
| 45 #include "chrome/common/net/url_fixer_upper.h" | 45 #include "chrome/common/net/url_fixer_upper.h" |
| 46 #include "chrome/common/pref_names.h" | 46 #include "chrome/common/pref_names.h" |
| 47 #include "chrome/common/url_constants.h" | 47 #include "chrome/common/url_constants.h" |
| 48 #include "content/public/browser/user_metrics.h" |
| 48 #include "grit/generated_resources.h" | 49 #include "grit/generated_resources.h" |
| 49 #include "net/base/escape.h" | 50 #include "net/base/escape.h" |
| 50 #include "net/base/load_flags.h" | 51 #include "net/base/load_flags.h" |
| 51 #include "net/base/net_util.h" | 52 #include "net/base/net_util.h" |
| 52 #include "net/base/registry_controlled_domains/registry_controlled_domain.h" | 53 #include "net/base/registry_controlled_domains/registry_controlled_domain.h" |
| 53 #include "net/http/http_request_headers.h" | 54 #include "net/http/http_request_headers.h" |
| 54 #include "net/http/http_response_headers.h" | 55 #include "net/http/http_response_headers.h" |
| 55 #include "net/url_request/url_fetcher.h" | 56 #include "net/url_request/url_fetcher.h" |
| 56 #include "net/url_request/url_request_status.h" | 57 #include "net/url_request/url_request_status.h" |
| 57 #include "ui/base/l10n/l10n_util.h" | 58 #include "ui/base/l10n/l10n_util.h" |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 168 } | 169 } |
| 169 | 170 |
| 170 if (!annotation.empty() && (annotation_start >= match_contents_start)) | 171 if (!annotation.empty() && (annotation_start >= match_contents_start)) |
| 171 match->contents_class.push_back(ACMatchClassification( | 172 match->contents_class.push_back(ACMatchClassification( |
| 172 match_contents_end, ACMatchClassification::DIM)); | 173 match_contents_end, ACMatchClassification::DIM)); |
| 173 } | 174 } |
| 174 | 175 |
| 175 } // namespace | 176 } // namespace |
| 176 | 177 |
| 177 | 178 |
| 179 // SuggestionDeletionHandler ------------------------------------------------- |
| 180 |
| 181 // This class handles making requests to the server in order to delete |
| 182 // personalized suggestions. |
| 183 class SuggestionDeletionHandler : public net::URLFetcherDelegate { |
| 184 public: |
| 185 typedef base::Callback<void(bool, SuggestionDeletionHandler*)> |
| 186 DeletionCompletedCallback; |
| 187 |
| 188 SuggestionDeletionHandler( |
| 189 const std::string& deletion_url, |
| 190 Profile* profile, |
| 191 const DeletionCompletedCallback& callback); |
| 192 |
| 193 virtual ~SuggestionDeletionHandler(); |
| 194 |
| 195 private: |
| 196 // net::URLFetcherDelegate: |
| 197 virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE; |
| 198 |
| 199 scoped_ptr<net::URLFetcher> deletion_fetcher_; |
| 200 DeletionCompletedCallback callback_; |
| 201 |
| 202 DISALLOW_COPY_AND_ASSIGN(SuggestionDeletionHandler); |
| 203 }; |
| 204 |
| 205 |
| 206 SuggestionDeletionHandler::SuggestionDeletionHandler( |
| 207 const std::string& deletion_url, |
| 208 Profile* profile, |
| 209 const DeletionCompletedCallback& callback) : callback_(callback) { |
| 210 GURL url(deletion_url); |
| 211 DCHECK(url.is_valid()); |
| 212 |
| 213 deletion_fetcher_.reset(net::URLFetcher::Create( |
| 214 SearchProvider::kDeletionURLFetcherID, |
| 215 url, |
| 216 net::URLFetcher::GET, |
| 217 this)); |
| 218 deletion_fetcher_->SetRequestContext(profile->GetRequestContext()); |
| 219 deletion_fetcher_->Start(); |
| 220 }; |
| 221 |
| 222 SuggestionDeletionHandler::~SuggestionDeletionHandler() { |
| 223 }; |
| 224 |
| 225 void SuggestionDeletionHandler::OnURLFetchComplete( |
| 226 const net::URLFetcher* source) { |
| 227 DCHECK(source == deletion_fetcher_.get()); |
| 228 callback_.Run( |
| 229 source->GetStatus().is_success() && (source->GetResponseCode() == 200), |
| 230 this); |
| 231 }; |
| 232 |
| 233 |
| 178 // SearchProvider::Providers -------------------------------------------------- | 234 // SearchProvider::Providers -------------------------------------------------- |
| 179 | 235 |
| 180 SearchProvider::Providers::Providers(TemplateURLService* template_url_service) | 236 SearchProvider::Providers::Providers(TemplateURLService* template_url_service) |
| 181 : template_url_service_(template_url_service) { | 237 : template_url_service_(template_url_service) { |
| 182 } | 238 } |
| 183 | 239 |
| 184 const TemplateURL* SearchProvider::Providers::GetDefaultProviderURL() const { | 240 const TemplateURL* SearchProvider::Providers::GetDefaultProviderURL() const { |
| 185 return default_provider_.empty() ? NULL : | 241 return default_provider_.empty() ? NULL : |
| 186 template_url_service_->GetTemplateURLForKeyword(default_provider_); | 242 template_url_service_->GetTemplateURLForKeyword(default_provider_); |
| 187 } | 243 } |
| (...skipping 18 matching lines...) Expand all Loading... |
| 206 } | 262 } |
| 207 | 263 |
| 208 | 264 |
| 209 // SearchProvider::SuggestResult ---------------------------------------------- | 265 // SearchProvider::SuggestResult ---------------------------------------------- |
| 210 | 266 |
| 211 SearchProvider::SuggestResult::SuggestResult( | 267 SearchProvider::SuggestResult::SuggestResult( |
| 212 const string16& suggestion, | 268 const string16& suggestion, |
| 213 const string16& match_contents, | 269 const string16& match_contents, |
| 214 const string16& annotation, | 270 const string16& annotation, |
| 215 const std::string& suggest_query_params, | 271 const std::string& suggest_query_params, |
| 272 const std::string& deletion_url, |
| 216 bool from_keyword_provider, | 273 bool from_keyword_provider, |
| 217 int relevance, | 274 int relevance, |
| 218 bool relevance_from_server, | 275 bool relevance_from_server, |
| 219 bool should_prefetch) | 276 bool should_prefetch) |
| 220 : Result(from_keyword_provider, relevance, relevance_from_server), | 277 : Result(from_keyword_provider, relevance, relevance_from_server), |
| 221 suggestion_(suggestion), | 278 suggestion_(suggestion), |
| 222 match_contents_(match_contents), | 279 match_contents_(match_contents), |
| 223 annotation_(annotation), | 280 annotation_(annotation), |
| 224 suggest_query_params_(suggest_query_params), | 281 suggest_query_params_(suggest_query_params), |
| 282 deletion_url_(deletion_url), |
| 225 should_prefetch_(should_prefetch) { | 283 should_prefetch_(should_prefetch) { |
| 226 } | 284 } |
| 227 | 285 |
| 228 SearchProvider::SuggestResult::~SuggestResult() { | 286 SearchProvider::SuggestResult::~SuggestResult() { |
| 229 } | 287 } |
| 230 | 288 |
| 231 bool SearchProvider::SuggestResult::IsInlineable(const string16& input) const { | 289 bool SearchProvider::SuggestResult::IsInlineable(const string16& input) const { |
| 232 return StartsWith(suggestion_, input, false); | 290 return StartsWith(suggestion_, input, false); |
| 233 } | 291 } |
| 234 | 292 |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 319 | 377 |
| 320 return false; | 378 return false; |
| 321 } | 379 } |
| 322 | 380 |
| 323 | 381 |
| 324 // SearchProvider ------------------------------------------------------------- | 382 // SearchProvider ------------------------------------------------------------- |
| 325 | 383 |
| 326 // static | 384 // static |
| 327 const int SearchProvider::kDefaultProviderURLFetcherID = 1; | 385 const int SearchProvider::kDefaultProviderURLFetcherID = 1; |
| 328 const int SearchProvider::kKeywordProviderURLFetcherID = 2; | 386 const int SearchProvider::kKeywordProviderURLFetcherID = 2; |
| 387 const int SearchProvider::kDeletionURLFetcherID = 3; |
| 329 int SearchProvider::kMinimumTimeBetweenSuggestQueriesMs = 100; | 388 int SearchProvider::kMinimumTimeBetweenSuggestQueriesMs = 100; |
| 330 const char SearchProvider::kRelevanceFromServerKey[] = "relevance_from_server"; | 389 const char SearchProvider::kRelevanceFromServerKey[] = "relevance_from_server"; |
| 331 const char SearchProvider::kShouldPrefetchKey[] = "should_prefetch"; | 390 const char SearchProvider::kShouldPrefetchKey[] = "should_prefetch"; |
| 332 const char SearchProvider::kSuggestMetadataKey[] = "suggest_metadata"; | 391 const char SearchProvider::kSuggestMetadataKey[] = "suggest_metadata"; |
| 392 const char SearchProvider::kDeletionUrlKey[] = "deletion_url"; |
| 333 const char SearchProvider::kTrue[] = "true"; | 393 const char SearchProvider::kTrue[] = "true"; |
| 334 const char SearchProvider::kFalse[] = "false"; | 394 const char SearchProvider::kFalse[] = "false"; |
| 335 | 395 |
| 336 SearchProvider::SearchProvider(AutocompleteProviderListener* listener, | 396 SearchProvider::SearchProvider(AutocompleteProviderListener* listener, |
| 337 Profile* profile) | 397 Profile* profile) |
| 338 : AutocompleteProvider(listener, profile, | 398 : AutocompleteProvider(listener, profile, |
| 339 AutocompleteProvider::TYPE_SEARCH), | 399 AutocompleteProvider::TYPE_SEARCH), |
| 340 providers_(TemplateURLServiceFactory::GetForProfile(profile)), | 400 providers_(TemplateURLServiceFactory::GetForProfile(profile)), |
| 341 suggest_results_pending_(0), | 401 suggest_results_pending_(0), |
| 342 field_trial_triggered_(false), | 402 field_trial_triggered_(false), |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 427 for (size_t i = 0; i < field_trial_hashes.size(); ++i) { | 487 for (size_t i = 0; i < field_trial_hashes.size(); ++i) { |
| 428 if (field_trial_triggered_) | 488 if (field_trial_triggered_) |
| 429 new_entry.mutable_field_trial_triggered()->Add(field_trial_hashes[i]); | 489 new_entry.mutable_field_trial_triggered()->Add(field_trial_hashes[i]); |
| 430 if (field_trial_triggered_in_session_) { | 490 if (field_trial_triggered_in_session_) { |
| 431 new_entry.mutable_field_trial_triggered_in_session()->Add( | 491 new_entry.mutable_field_trial_triggered_in_session()->Add( |
| 432 field_trial_hashes[i]); | 492 field_trial_hashes[i]); |
| 433 } | 493 } |
| 434 } | 494 } |
| 435 } | 495 } |
| 436 | 496 |
| 497 void SearchProvider::DeleteMatch(const AutocompleteMatch& match) { |
| 498 // TODO(mariakhomenko): Add support for deleting search history suggestions. |
| 499 DCHECK(match.deletable); |
| 500 |
| 501 deletion_handlers_.push_back(new SuggestionDeletionHandler( |
| 502 match.GetAdditionalInfo(SearchProvider::kDeletionUrlKey), |
| 503 profile_, |
| 504 base::Bind(&SearchProvider::OnDeletionComplete, base::Unretained(this)))); |
| 505 |
| 506 // Immediately update the list of matches to show the match was deleted, |
| 507 // regardless of whether the server request actually succeeds. |
| 508 DeleteMatchFromMatches(match); |
| 509 } |
| 510 |
| 437 void SearchProvider::ResetSession() { | 511 void SearchProvider::ResetSession() { |
| 438 field_trial_triggered_in_session_ = false; | 512 field_trial_triggered_in_session_ = false; |
| 439 } | 513 } |
| 440 | 514 |
| 441 SearchProvider::~SearchProvider() { | 515 SearchProvider::~SearchProvider() { |
| 442 } | 516 } |
| 443 | 517 |
| 444 // static | 518 // static |
| 445 void SearchProvider::RemoveStaleResults(const string16& input, | 519 void SearchProvider::RemoveStaleResults(const string16& input, |
| 446 int verbatim_relevance, | 520 int verbatim_relevance, |
| (...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 631 elapsed_time); | 705 elapsed_time); |
| 632 } | 706 } |
| 633 } | 707 } |
| 634 | 708 |
| 635 bool results_updated = false; | 709 bool results_updated = false; |
| 636 if (request_succeeded) { | 710 if (request_succeeded) { |
| 637 const net::HttpResponseHeaders* const response_headers = | 711 const net::HttpResponseHeaders* const response_headers = |
| 638 source->GetResponseHeaders(); | 712 source->GetResponseHeaders(); |
| 639 std::string json_data; | 713 std::string json_data; |
| 640 source->GetResponseAsString(&json_data); | 714 source->GetResponseAsString(&json_data); |
| 715 |
| 641 // JSON is supposed to be UTF-8, but some suggest service providers send | 716 // JSON is supposed to be UTF-8, but some suggest service providers send |
| 642 // JSON files in non-UTF-8 encodings. The actual encoding is usually | 717 // JSON files in non-UTF-8 encodings. The actual encoding is usually |
| 643 // specified in the Content-Type header field. | 718 // specified in the Content-Type header field. |
| 644 if (response_headers) { | 719 if (response_headers) { |
| 645 std::string charset; | 720 std::string charset; |
| 646 if (response_headers->GetCharset(&charset)) { | 721 if (response_headers->GetCharset(&charset)) { |
| 647 string16 data_16; | 722 string16 data_16; |
| 648 // TODO(jungshik): Switch to CodePageToUTF8 after it's added. | 723 // TODO(jungshik): Switch to CodePageToUTF8 after it's added. |
| 649 if (base::CodepageToUTF16(json_data, charset.c_str(), | 724 if (base::CodepageToUTF16(json_data, charset.c_str(), |
| 650 base::OnStringConversionError::FAIL, | 725 base::OnStringConversionError::FAIL, |
| (...skipping 20 matching lines...) Expand all Loading... |
| 671 break; | 746 break; |
| 672 } | 747 } |
| 673 } | 748 } |
| 674 } | 749 } |
| 675 | 750 |
| 676 UpdateMatches(); | 751 UpdateMatches(); |
| 677 if (done_ || results_updated) | 752 if (done_ || results_updated) |
| 678 listener_->OnProviderUpdate(results_updated); | 753 listener_->OnProviderUpdate(results_updated); |
| 679 } | 754 } |
| 680 | 755 |
| 756 void SearchProvider::OnDeletionComplete(bool success, |
| 757 SuggestionDeletionHandler* handler) { |
| 758 RecordDeletionResult(success); |
| 759 SuggestionDeletionHandlers::iterator it = std::find( |
| 760 deletion_handlers_.begin(), deletion_handlers_.end(), handler); |
| 761 DCHECK(it != deletion_handlers_.end()); |
| 762 deletion_handlers_.erase(it); |
| 763 } |
| 764 |
| 765 |
| 766 void SearchProvider::RecordDeletionResult(bool success) { |
| 767 if (success) { |
| 768 content::RecordAction( |
| 769 content::UserMetricsAction("Omnibox.ServerSuggestDelete.Success")); |
| 770 } else { |
| 771 content::RecordAction( |
| 772 content::UserMetricsAction("Omnibox.ServerSuggestDelete.Failure")); |
| 773 } |
| 774 } |
| 775 |
| 776 void SearchProvider::DeleteMatchFromMatches(const AutocompleteMatch& match) { |
| 777 for (ACMatches::iterator i(matches_.begin()); i != matches_.end(); ++i) { |
| 778 // Find the desired match to delete by checking the type and contents. |
| 779 // We can't check the destination URL, because the autocomplete controller |
| 780 // may have reformulated that. Not that while checking for matching |
| 781 // contents works for personalized suggestions, if more match types gain |
| 782 // deletion support, this algorithm may need to be re-examined. |
| 783 if (i->contents == match.contents && i->type == match.type) { |
| 784 matches_.erase(i); |
| 785 break; |
| 786 } |
| 787 } |
| 788 listener_->OnProviderUpdate(true); |
| 789 } |
| 790 |
| 681 void SearchProvider::Run() { | 791 void SearchProvider::Run() { |
| 682 // Start a new request with the current input. | 792 // Start a new request with the current input. |
| 683 suggest_results_pending_ = 0; | 793 suggest_results_pending_ = 0; |
| 684 time_suggest_request_sent_ = base::TimeTicks::Now(); | 794 time_suggest_request_sent_ = base::TimeTicks::Now(); |
| 685 | 795 |
| 686 default_fetcher_.reset(CreateSuggestFetcher(kDefaultProviderURLFetcherID, | 796 default_fetcher_.reset(CreateSuggestFetcher(kDefaultProviderURLFetcherID, |
| 687 providers_.GetDefaultProviderURL(), input_)); | 797 providers_.GetDefaultProviderURL(), input_)); |
| 688 keyword_fetcher_.reset(CreateSuggestFetcher(kKeywordProviderURLFetcherID, | 798 keyword_fetcher_.reset(CreateSuggestFetcher(kKeywordProviderURLFetcherID, |
| 689 providers_.GetKeywordProviderURL(), keyword_input_)); | 799 providers_.GetKeywordProviderURL(), keyword_input_)); |
| 690 | 800 |
| (...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 928 NavigationResults* list) { | 1038 NavigationResults* list) { |
| 929 for (size_t i = 0; i < list->size(); ++i) { | 1039 for (size_t i = 0; i < list->size(); ++i) { |
| 930 NavigationResult& result = (*list)[i]; | 1040 NavigationResult& result = (*list)[i]; |
| 931 result.set_relevance( | 1041 result.set_relevance( |
| 932 result.CalculateRelevance(input_, providers_.has_keyword_provider()) + | 1042 result.CalculateRelevance(input_, providers_.has_keyword_provider()) + |
| 933 (list->size() - i - 1)); | 1043 (list->size() - i - 1)); |
| 934 result.set_relevance_from_server(false); | 1044 result.set_relevance_from_server(false); |
| 935 } | 1045 } |
| 936 } | 1046 } |
| 937 | 1047 |
| 938 bool SearchProvider::CanSendURL( | |
| 939 const GURL& current_page_url, | |
| 940 const GURL& suggest_url, | |
| 941 const TemplateURL* template_url, | |
| 942 AutocompleteInput::PageClassification page_classification, | |
| 943 Profile* profile) { | |
| 944 if (!current_page_url.is_valid()) | |
| 945 return false; | |
| 946 | |
| 947 // TODO(hfung): Show Most Visited on NTP with appropriate verbatim | |
| 948 // description when the user actively focuses on the omnibox as discussed in | |
| 949 // crbug/305366 if Most Visited (or something similar) will launch. | |
| 950 if ((page_classification == | |
| 951 AutocompleteInput::INSTANT_NTP_WITH_FAKEBOX_AS_STARTING_FOCUS) || | |
| 952 (page_classification == | |
| 953 AutocompleteInput::INSTANT_NTP_WITH_OMNIBOX_AS_STARTING_FOCUS)) | |
| 954 return false; | |
| 955 | |
| 956 // Only allow HTTP URLs or HTTPS URLs for the same domain as the search | |
| 957 // provider. | |
| 958 if ((current_page_url.scheme() != content::kHttpScheme) && | |
| 959 ((current_page_url.scheme() != content::kHttpsScheme) || | |
| 960 !net::registry_controlled_domains::SameDomainOrHost( | |
| 961 current_page_url, suggest_url, | |
| 962 net::registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES))) | |
| 963 return false; | |
| 964 | |
| 965 // Make sure we are sending the suggest request through HTTPS to prevent | |
| 966 // exposing the current page URL to networks before the search provider. | |
| 967 if (!suggest_url.SchemeIs(content::kHttpsScheme)) | |
| 968 return false; | |
| 969 | |
| 970 // Don't run if there's no profile or in incognito mode. | |
| 971 if (profile == NULL || profile->IsOffTheRecord()) | |
| 972 return false; | |
| 973 | |
| 974 // Don't run if we can't get preferences or search suggest is not enabled. | |
| 975 PrefService* prefs = profile->GetPrefs(); | |
| 976 if (!prefs->GetBoolean(prefs::kSearchSuggestEnabled)) | |
| 977 return false; | |
| 978 | |
| 979 // Only make the request if we know that the provider supports zero suggest | |
| 980 // (currently only the prepopulated Google provider). | |
| 981 if (template_url == NULL || !template_url->SupportsReplacement() || | |
| 982 TemplateURLPrepopulateData::GetEngineType(*template_url) != | |
| 983 SEARCH_ENGINE_GOOGLE) | |
| 984 return false; | |
| 985 | |
| 986 // Check field trials and settings allow sending the URL on suggest requests. | |
| 987 ProfileSyncService* service = | |
| 988 ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile); | |
| 989 browser_sync::SyncPrefs sync_prefs(prefs); | |
| 990 if (!OmniboxFieldTrial::InZeroSuggestFieldTrial() || | |
| 991 service == NULL || | |
| 992 !service->IsSyncEnabledAndLoggedIn() || | |
| 993 !sync_prefs.GetPreferredDataTypes(syncer::UserTypes()).Has( | |
| 994 syncer::PROXY_TABS) || | |
| 995 service->GetEncryptedDataTypes().Has(syncer::SESSIONS)) | |
| 996 return false; | |
| 997 | |
| 998 return true; | |
| 999 } | |
| 1000 | |
| 1001 net::URLFetcher* SearchProvider::CreateSuggestFetcher( | 1048 net::URLFetcher* SearchProvider::CreateSuggestFetcher( |
| 1002 int id, | 1049 int id, |
| 1003 const TemplateURL* template_url, | 1050 const TemplateURL* template_url, |
| 1004 const AutocompleteInput& input) { | 1051 const AutocompleteInput& input) { |
| 1005 if (!template_url || template_url->suggestions_url().empty()) | 1052 if (!template_url || template_url->suggestions_url().empty()) |
| 1006 return NULL; | 1053 return NULL; |
| 1007 | 1054 |
| 1008 // Bail if the suggestion URL is invalid with the given replacements. | 1055 // Bail if the suggestion URL is invalid with the given replacements. |
| 1009 TemplateURLRef::SearchTermsArgs search_term_args(input.text()); | 1056 TemplateURLRef::SearchTermsArgs search_term_args(input.text()); |
| 1010 search_term_args.cursor_position = input.cursor_position(); | 1057 search_term_args.cursor_position = input.cursor_position(); |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1124 string16 title; | 1171 string16 title; |
| 1125 if (descriptions != NULL) | 1172 if (descriptions != NULL) |
| 1126 descriptions->GetString(index, &title); | 1173 descriptions->GetString(index, &title); |
| 1127 results->navigation_results.push_back(NavigationResult( | 1174 results->navigation_results.push_back(NavigationResult( |
| 1128 *this, url, title, is_keyword, relevance, true)); | 1175 *this, url, title, is_keyword, relevance, true)); |
| 1129 } | 1176 } |
| 1130 } else { | 1177 } else { |
| 1131 bool should_prefetch = static_cast<int>(index) == prefetch_index; | 1178 bool should_prefetch = static_cast<int>(index) == prefetch_index; |
| 1132 DictionaryValue* suggestion_detail = NULL; | 1179 DictionaryValue* suggestion_detail = NULL; |
| 1133 string16 match_contents = suggestion; | 1180 string16 match_contents = suggestion; |
| 1134 string16 disambiguating_query; | |
| 1135 string16 annotation; | 1181 string16 annotation; |
| 1136 std::string suggest_query_params; | 1182 std::string suggest_query_params; |
| 1137 if (suggestion_details && (type == "ENTITY") && | 1183 std::string deletion_url; |
| 1138 suggestion_details->GetDictionary(index, &suggestion_detail) && | 1184 |
| 1139 suggestion_detail) { | 1185 if (suggestion_details) { |
| 1140 suggestion_detail->GetString("a", &annotation); | 1186 suggestion_details->GetDictionary(index, &suggestion_detail); |
| 1141 if (suggestion_detail->GetString("dq", &disambiguating_query) && | 1187 if (suggestion_detail) { |
| 1142 !disambiguating_query.empty()) | 1188 suggestion_detail->GetString("du", &deletion_url); |
| 1143 suggestion = disambiguating_query; | 1189 |
| 1144 suggestion_detail->GetString("q", &suggest_query_params); | 1190 if (type == "ENTITY") { |
| 1191 suggestion_detail->GetString("a", &annotation); |
| 1192 |
| 1193 string16 disambiguating_query; |
| 1194 if (suggestion_detail->GetString("dq", &disambiguating_query) && |
| 1195 !disambiguating_query.empty()) |
| 1196 suggestion = disambiguating_query; |
| 1197 |
| 1198 suggestion_detail->GetString("q", &suggest_query_params); |
| 1199 } |
| 1200 } |
| 1145 } | 1201 } |
| 1202 |
| 1146 // TODO(kochi): Improve calculator suggestion presentation. | 1203 // TODO(kochi): Improve calculator suggestion presentation. |
| 1147 results->suggest_results.push_back(SuggestResult( | 1204 results->suggest_results.push_back(SuggestResult( |
| 1148 suggestion, match_contents, annotation, suggest_query_params, | 1205 suggestion, match_contents, annotation, suggest_query_params, |
| 1149 is_keyword, relevance, true, should_prefetch)); | 1206 deletion_url, is_keyword, relevance, true, should_prefetch)); |
| 1150 } | 1207 } |
| 1151 } | 1208 } |
| 1152 | 1209 |
| 1153 // Ignore suggested scores for non-keyword matches in keyword mode; if the | 1210 // Ignore suggested scores for non-keyword matches in keyword mode; if the |
| 1154 // server is allowed to score these, it could interfere with the user's | 1211 // server is allowed to score these, it could interfere with the user's |
| 1155 // ability to get good keyword results. | 1212 // ability to get good keyword results. |
| 1156 const bool abandon_suggested_scores = | 1213 const bool abandon_suggested_scores = |
| 1157 !is_keyword && !providers_.keyword_provider().empty(); | 1214 !is_keyword && !providers_.keyword_provider().empty(); |
| 1158 // Apply calculated relevance scores to suggestions if a valid list was | 1215 // Apply calculated relevance scores to suggestions if a valid list was |
| 1159 // not provided or we're abandoning suggested scores entirely. | 1216 // not provided or we're abandoning suggested scores entirely. |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1199 relevance_from_server, | 1256 relevance_from_server, |
| 1200 false, | 1257 false, |
| 1201 std::string(), | 1258 std::string(), |
| 1202 AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED, | 1259 AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED, |
| 1203 false, | 1260 false, |
| 1204 input_.text(), | 1261 input_.text(), |
| 1205 string16(), | 1262 string16(), |
| 1206 input_.text(), | 1263 input_.text(), |
| 1207 did_not_accept_default_suggestion, | 1264 did_not_accept_default_suggestion, |
| 1208 std::string(), | 1265 std::string(), |
| 1266 std::string(), |
| 1209 &map); | 1267 &map); |
| 1210 } | 1268 } |
| 1211 if (!keyword_input_.text().empty()) { | 1269 if (!keyword_input_.text().empty()) { |
| 1212 const TemplateURL* keyword_url = providers_.GetKeywordProviderURL(); | 1270 const TemplateURL* keyword_url = providers_.GetKeywordProviderURL(); |
| 1213 // We only create the verbatim search query match for a keyword | 1271 // We only create the verbatim search query match for a keyword |
| 1214 // if it's not an extension keyword. Extension keywords are handled | 1272 // if it's not an extension keyword. Extension keywords are handled |
| 1215 // in KeywordProvider::Start(). (Extensions are complicated...) | 1273 // in KeywordProvider::Start(). (Extensions are complicated...) |
| 1216 // Note: in this provider, SEARCH_OTHER_ENGINE must correspond | 1274 // Note: in this provider, SEARCH_OTHER_ENGINE must correspond |
| 1217 // to the keyword verbatim search query. Do not create other matches | 1275 // to the keyword verbatim search query. Do not create other matches |
| 1218 // of type SEARCH_OTHER_ENGINE. | 1276 // of type SEARCH_OTHER_ENGINE. |
| 1219 if (keyword_url && | 1277 if (keyword_url && |
| 1220 (keyword_url->GetType() != TemplateURL::OMNIBOX_API_EXTENSION)) { | 1278 (keyword_url->GetType() != TemplateURL::OMNIBOX_API_EXTENSION)) { |
| 1221 bool keyword_relevance_from_server; | 1279 bool keyword_relevance_from_server; |
| 1222 const int keyword_verbatim_relevance = | 1280 const int keyword_verbatim_relevance = |
| 1223 GetKeywordVerbatimRelevance(&keyword_relevance_from_server); | 1281 GetKeywordVerbatimRelevance(&keyword_relevance_from_server); |
| 1224 if (keyword_verbatim_relevance > 0) { | 1282 if (keyword_verbatim_relevance > 0) { |
| 1225 AddMatchToMap(keyword_input_.text(), | 1283 AddMatchToMap(keyword_input_.text(), |
| 1226 keyword_verbatim_relevance, | 1284 keyword_verbatim_relevance, |
| 1227 keyword_relevance_from_server, | 1285 keyword_relevance_from_server, |
| 1228 false, | 1286 false, |
| 1229 std::string(), | 1287 std::string(), |
| 1230 AutocompleteMatchType::SEARCH_OTHER_ENGINE, | 1288 AutocompleteMatchType::SEARCH_OTHER_ENGINE, |
| 1231 true, | 1289 true, |
| 1232 keyword_input_.text(), | 1290 keyword_input_.text(), |
| 1233 string16(), | 1291 string16(), |
| 1234 keyword_input_.text(), | 1292 keyword_input_.text(), |
| 1235 did_not_accept_keyword_suggestion, | 1293 did_not_accept_keyword_suggestion, |
| 1236 std::string(), | 1294 std::string(), |
| 1295 std::string(), |
| 1237 &map); | 1296 &map); |
| 1238 } | 1297 } |
| 1239 } | 1298 } |
| 1240 } | 1299 } |
| 1241 AddHistoryResultsToMap(keyword_history_results_, true, | 1300 AddHistoryResultsToMap(keyword_history_results_, true, |
| 1242 did_not_accept_keyword_suggestion, &map); | 1301 did_not_accept_keyword_suggestion, &map); |
| 1243 AddHistoryResultsToMap(default_history_results_, false, | 1302 AddHistoryResultsToMap(default_history_results_, false, |
| 1244 did_not_accept_default_suggestion, &map); | 1303 did_not_accept_default_suggestion, &map); |
| 1245 | 1304 |
| 1246 AddSuggestResultsToMap(keyword_results_.suggest_results, | 1305 AddSuggestResultsToMap(keyword_results_.suggest_results, |
| (...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1535 false, | 1594 false, |
| 1536 false, | 1595 false, |
| 1537 std::string(), | 1596 std::string(), |
| 1538 AutocompleteMatchType::SEARCH_HISTORY, | 1597 AutocompleteMatchType::SEARCH_HISTORY, |
| 1539 is_keyword, | 1598 is_keyword, |
| 1540 i->suggestion(), | 1599 i->suggestion(), |
| 1541 string16(), | 1600 string16(), |
| 1542 i->suggestion(), | 1601 i->suggestion(), |
| 1543 did_not_accept_suggestion, | 1602 did_not_accept_suggestion, |
| 1544 std::string(), | 1603 std::string(), |
| 1604 std::string(), |
| 1545 map); | 1605 map); |
| 1546 } | 1606 } |
| 1547 UMA_HISTOGRAM_TIMES("Omnibox.SearchProvider.AddHistoryResultsTime", | 1607 UMA_HISTOGRAM_TIMES("Omnibox.SearchProvider.AddHistoryResultsTime", |
| 1548 base::TimeTicks::Now() - start_time); | 1608 base::TimeTicks::Now() - start_time); |
| 1549 } | 1609 } |
| 1550 | 1610 |
| 1551 SearchProvider::SuggestResults SearchProvider::ScoreHistoryResults( | 1611 SearchProvider::SuggestResults SearchProvider::ScoreHistoryResults( |
| 1552 const HistoryResults& results, | 1612 const HistoryResults& results, |
| 1553 bool base_prevent_inline_autocomplete, | 1613 bool base_prevent_inline_autocomplete, |
| 1554 bool input_multiple_words, | 1614 bool input_multiple_words, |
| (...skipping 30 matching lines...) Expand all Loading... |
| 1585 classifier->Classify(i->term, false, false, &match, NULL); | 1645 classifier->Classify(i->term, false, false, &match, NULL); |
| 1586 prevent_inline_autocomplete = | 1646 prevent_inline_autocomplete = |
| 1587 !AutocompleteMatch::IsSearchType(match.type); | 1647 !AutocompleteMatch::IsSearchType(match.type); |
| 1588 } | 1648 } |
| 1589 | 1649 |
| 1590 int relevance = CalculateRelevanceForHistory( | 1650 int relevance = CalculateRelevanceForHistory( |
| 1591 i->time, is_keyword, !prevent_inline_autocomplete, | 1651 i->time, is_keyword, !prevent_inline_autocomplete, |
| 1592 prevent_search_history_inlining); | 1652 prevent_search_history_inlining); |
| 1593 scored_results.push_back( | 1653 scored_results.push_back( |
| 1594 SuggestResult(i->term, string16(), string16(), std::string(), | 1654 SuggestResult(i->term, string16(), string16(), std::string(), |
| 1595 is_keyword, relevance, false, false)); | 1655 std::string(), is_keyword, relevance, false, false)); |
| 1596 } | 1656 } |
| 1597 | 1657 |
| 1598 // History returns results sorted for us. However, we may have docked some | 1658 // History returns results sorted for us. However, we may have docked some |
| 1599 // results' scores, so things are no longer in order. Do a stable sort to get | 1659 // results' scores, so things are no longer in order. Do a stable sort to get |
| 1600 // things back in order without otherwise disturbing results with equal | 1660 // things back in order without otherwise disturbing results with equal |
| 1601 // scores, then force the scores to be unique, so that the order in which | 1661 // scores, then force the scores to be unique, so that the order in which |
| 1602 // they're shown is deterministic. | 1662 // they're shown is deterministic. |
| 1603 std::stable_sort(scored_results.begin(), scored_results.end(), | 1663 std::stable_sort(scored_results.begin(), scored_results.end(), |
| 1604 CompareScoredResults()); | 1664 CompareScoredResults()); |
| 1605 int last_relevance = 0; | 1665 int last_relevance = 0; |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1624 results[i].relevance_from_server(), | 1684 results[i].relevance_from_server(), |
| 1625 results[i].should_prefetch(), | 1685 results[i].should_prefetch(), |
| 1626 metadata, | 1686 metadata, |
| 1627 AutocompleteMatchType::SEARCH_SUGGEST, | 1687 AutocompleteMatchType::SEARCH_SUGGEST, |
| 1628 is_keyword, | 1688 is_keyword, |
| 1629 results[i].match_contents(), | 1689 results[i].match_contents(), |
| 1630 results[i].annotation(), | 1690 results[i].annotation(), |
| 1631 results[i].suggestion(), | 1691 results[i].suggestion(), |
| 1632 i, | 1692 i, |
| 1633 results[i].suggest_query_params(), | 1693 results[i].suggest_query_params(), |
| 1694 results[i].deletion_url(), |
| 1634 map); | 1695 map); |
| 1635 } | 1696 } |
| 1636 } | 1697 } |
| 1637 | 1698 |
| 1638 int SearchProvider::GetVerbatimRelevance(bool* relevance_from_server) const { | 1699 int SearchProvider::GetVerbatimRelevance(bool* relevance_from_server) const { |
| 1639 // Use the suggested verbatim relevance score if it is non-negative (valid), | 1700 // Use the suggested verbatim relevance score if it is non-negative (valid), |
| 1640 // if inline autocomplete isn't prevented (always show verbatim on backspace), | 1701 // if inline autocomplete isn't prevented (always show verbatim on backspace), |
| 1641 // and if it won't suppress verbatim, leaving no default provider matches. | 1702 // and if it won't suppress verbatim, leaving no default provider matches. |
| 1642 // Otherwise, if the default provider returned no matches and was still able | 1703 // Otherwise, if the default provider returned no matches and was still able |
| 1643 // to suppress verbatim, the user would have no search/nav matches and may be | 1704 // to suppress verbatim, the user would have no search/nav matches and may be |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1748 bool relevance_from_server, | 1809 bool relevance_from_server, |
| 1749 bool should_prefetch, | 1810 bool should_prefetch, |
| 1750 const std::string& metadata, | 1811 const std::string& metadata, |
| 1751 AutocompleteMatch::Type type, | 1812 AutocompleteMatch::Type type, |
| 1752 bool is_keyword, | 1813 bool is_keyword, |
| 1753 const string16& match_contents, | 1814 const string16& match_contents, |
| 1754 const string16& annotation, | 1815 const string16& annotation, |
| 1755 const string16& query_string, | 1816 const string16& query_string, |
| 1756 int accepted_suggestion, | 1817 int accepted_suggestion, |
| 1757 const std::string& suggest_query_params, | 1818 const std::string& suggest_query_params, |
| 1819 const std::string& deletion_url, |
| 1758 MatchMap* map) { | 1820 MatchMap* map) { |
| 1759 // On non-mobile, ask the instant controller for the appropriate start margin. | 1821 // On non-mobile, ask the instant controller for the appropriate start margin. |
| 1760 // On mobile the start margin is unused, so leave the value as default there. | 1822 // On mobile the start margin is unused, so leave the value as default there. |
| 1761 int omnibox_start_margin = chrome::kDisableStartMargin; | 1823 int omnibox_start_margin = chrome::kDisableStartMargin; |
| 1762 #if !defined(OS_ANDROID) && !defined(IOS) | 1824 #if !defined(OS_ANDROID) && !defined(IOS) |
| 1763 if (chrome::IsInstantExtendedAPIEnabled()) { | 1825 if (chrome::IsInstantExtendedAPIEnabled()) { |
| 1764 Browser* browser = | 1826 Browser* browser = |
| 1765 chrome::FindBrowserWithProfile(profile_, chrome::GetActiveDesktop()); | 1827 chrome::FindBrowserWithProfile(profile_, chrome::GetActiveDesktop()); |
| 1766 if (browser && browser->instant_controller() && | 1828 if (browser && browser->instant_controller() && |
| 1767 browser->instant_controller()->instant()) { | 1829 browser->instant_controller()->instant()) { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1780 !is_keyword || providers_.default_provider().empty()); | 1842 !is_keyword || providers_.default_provider().empty()); |
| 1781 if (!match.destination_url.is_valid()) | 1843 if (!match.destination_url.is_valid()) |
| 1782 return; | 1844 return; |
| 1783 match.search_terms_args->bookmark_bar_pinned = | 1845 match.search_terms_args->bookmark_bar_pinned = |
| 1784 profile_->GetPrefs()->GetBoolean(prefs::kShowBookmarkBar); | 1846 profile_->GetPrefs()->GetBoolean(prefs::kShowBookmarkBar); |
| 1785 match.RecordAdditionalInfo(kRelevanceFromServerKey, | 1847 match.RecordAdditionalInfo(kRelevanceFromServerKey, |
| 1786 relevance_from_server ? kTrue : kFalse); | 1848 relevance_from_server ? kTrue : kFalse); |
| 1787 match.RecordAdditionalInfo(kShouldPrefetchKey, | 1849 match.RecordAdditionalInfo(kShouldPrefetchKey, |
| 1788 should_prefetch ? kTrue : kFalse); | 1850 should_prefetch ? kTrue : kFalse); |
| 1789 | 1851 |
| 1852 if (!deletion_url.empty() && GURL(deletion_url).is_valid()) { |
| 1853 match.RecordAdditionalInfo(kDeletionUrlKey, deletion_url); |
| 1854 match.deletable = true; |
| 1855 } |
| 1856 |
| 1790 // Metadata is needed only for prefetching queries. | 1857 // Metadata is needed only for prefetching queries. |
| 1791 if (should_prefetch) | 1858 if (should_prefetch) |
| 1792 match.RecordAdditionalInfo(kSuggestMetadataKey, metadata); | 1859 match.RecordAdditionalInfo(kSuggestMetadataKey, metadata); |
| 1793 | 1860 |
| 1794 // Try to add |match| to |map|. If a match for |query_string| is already in | 1861 // Try to add |match| to |map|. If a match for |query_string| is already in |
| 1795 // |map|, replace it if |match| is more relevant. | 1862 // |map|, replace it if |match| is more relevant. |
| 1796 // NOTE: Keep this ToLower() call in sync with url_database.cc. | 1863 // NOTE: Keep this ToLower() call in sync with url_database.cc. |
| 1797 MatchKey match_key( | 1864 MatchKey match_key( |
| 1798 std::make_pair(base::i18n::ToLower(query_string), | 1865 std::make_pair(base::i18n::ToLower(query_string), |
| 1799 match.search_terms_args->suggest_query_params)); | 1866 match.search_terms_args->suggest_query_params)); |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1945 it->set_relevance(max_query_relevance); | 2012 it->set_relevance(max_query_relevance); |
| 1946 it->set_relevance_from_server(relevance_from_server); | 2013 it->set_relevance_from_server(relevance_from_server); |
| 1947 } | 2014 } |
| 1948 } | 2015 } |
| 1949 | 2016 |
| 1950 void SearchProvider::UpdateDone() { | 2017 void SearchProvider::UpdateDone() { |
| 1951 // We're done when the timer isn't running, there are no suggest queries | 2018 // We're done when the timer isn't running, there are no suggest queries |
| 1952 // pending, and we're not waiting on Instant. | 2019 // pending, and we're not waiting on Instant. |
| 1953 done_ = !timer_.IsRunning() && (suggest_results_pending_ == 0); | 2020 done_ = !timer_.IsRunning() && (suggest_results_pending_ == 0); |
| 1954 } | 2021 } |
| 2022 |
| 2023 bool SearchProvider::CanSendURL( |
| 2024 const GURL& current_page_url, |
| 2025 const GURL& suggest_url, |
| 2026 const TemplateURL* template_url, |
| 2027 AutocompleteInput::PageClassification page_classification, |
| 2028 Profile* profile) { |
| 2029 if (!current_page_url.is_valid()) |
| 2030 return false; |
| 2031 |
| 2032 // TODO(hfung): Show Most Visited on NTP with appropriate verbatim |
| 2033 // description when the user actively focuses on the omnibox as discussed in |
| 2034 // crbug/305366 if Most Visited (or something similar) will launch. |
| 2035 if ((page_classification == |
| 2036 AutocompleteInput::INSTANT_NTP_WITH_FAKEBOX_AS_STARTING_FOCUS) || |
| 2037 (page_classification == |
| 2038 AutocompleteInput::INSTANT_NTP_WITH_OMNIBOX_AS_STARTING_FOCUS)) |
| 2039 return false; |
| 2040 |
| 2041 // Only allow HTTP URLs or HTTPS URLs for the same domain as the search |
| 2042 // provider. |
| 2043 if ((current_page_url.scheme() != content::kHttpScheme) && |
| 2044 ((current_page_url.scheme() != content::kHttpsScheme) || |
| 2045 !net::registry_controlled_domains::SameDomainOrHost( |
| 2046 current_page_url, suggest_url, |
| 2047 net::registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES))) |
| 2048 return false; |
| 2049 |
| 2050 // Make sure we are sending the suggest request through HTTPS to prevent |
| 2051 // exposing the current page URL to networks before the search provider. |
| 2052 if (!suggest_url.SchemeIs(content::kHttpsScheme)) |
| 2053 return false; |
| 2054 |
| 2055 // Don't run if there's no profile or in incognito mode. |
| 2056 if (profile == NULL || profile->IsOffTheRecord()) |
| 2057 return false; |
| 2058 |
| 2059 // Don't run if we can't get preferences or search suggest is not enabled. |
| 2060 PrefService* prefs = profile->GetPrefs(); |
| 2061 if (!prefs->GetBoolean(prefs::kSearchSuggestEnabled)) |
| 2062 return false; |
| 2063 |
| 2064 // Only make the request if we know that the provider supports zero suggest |
| 2065 // (currently only the prepopulated Google provider). |
| 2066 if (template_url == NULL || !template_url->SupportsReplacement() || |
| 2067 TemplateURLPrepopulateData::GetEngineType(*template_url) != |
| 2068 SEARCH_ENGINE_GOOGLE) |
| 2069 return false; |
| 2070 |
| 2071 // Check field trials and settings allow sending the URL on suggest requests. |
| 2072 ProfileSyncService* service = |
| 2073 ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile); |
| 2074 browser_sync::SyncPrefs sync_prefs(prefs); |
| 2075 if (!OmniboxFieldTrial::InZeroSuggestFieldTrial() || |
| 2076 service == NULL || |
| 2077 !service->IsSyncEnabledAndLoggedIn() || |
| 2078 !sync_prefs.GetPreferredDataTypes(syncer::UserTypes()).Has( |
| 2079 syncer::PROXY_TABS) || |
| 2080 service->GetEncryptedDataTypes().Has(syncer::SESSIONS)) |
| 2081 return false; |
| 2082 |
| 2083 return true; |
| 2084 } |
| OLD | NEW |