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