| 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 "components/omnibox/browser/zero_suggest_provider.h" | 5 #include "components/omnibox/browser/zero_suggest_provider.h" | 
| 6 | 6 | 
| 7 #include <stddef.h> | 7 #include <stddef.h> | 
| 8 | 8 | 
| 9 #include "base/callback.h" | 9 #include "base/callback.h" | 
| 10 #include "base/i18n/case_conversion.h" | 10 #include "base/i18n/case_conversion.h" | 
| 11 #include "base/json/json_string_value_serializer.h" | 11 #include "base/json/json_string_value_serializer.h" | 
| 12 #include "base/metrics/histogram_macros.h" | 12 #include "base/metrics/histogram_macros.h" | 
| 13 #include "base/metrics/user_metrics.h" | 13 #include "base/metrics/user_metrics.h" | 
| 14 #include "base/strings/string16.h" | 14 #include "base/strings/string16.h" | 
| 15 #include "base/strings/string_util.h" | 15 #include "base/strings/string_util.h" | 
| 16 #include "base/strings/utf_string_conversions.h" | 16 #include "base/strings/utf_string_conversions.h" | 
| 17 #include "base/time/time.h" | 17 #include "base/time/time.h" | 
| 18 #include "base/trace_event/trace_event.h" | 18 #include "base/trace_event/trace_event.h" | 
| 19 #include "components/data_use_measurement/core/data_use_user_data.h" | 19 #include "components/data_use_measurement/core/data_use_user_data.h" | 
| 20 #include "components/history/core/browser/history_types.h" | 20 #include "components/history/core/browser/history_types.h" | 
| 21 #include "components/history/core/browser/top_sites.h" | 21 #include "components/history/core/browser/top_sites.h" | 
| 22 #include "components/metrics/proto/omnibox_event.pb.h" |  | 
| 23 #include "components/metrics/proto/omnibox_input_type.pb.h" | 22 #include "components/metrics/proto/omnibox_input_type.pb.h" | 
| 24 #include "components/omnibox/browser/autocomplete_classifier.h" | 23 #include "components/omnibox/browser/autocomplete_classifier.h" | 
| 25 #include "components/omnibox/browser/autocomplete_input.h" | 24 #include "components/omnibox/browser/autocomplete_input.h" | 
| 26 #include "components/omnibox/browser/autocomplete_match.h" | 25 #include "components/omnibox/browser/autocomplete_match.h" | 
| 27 #include "components/omnibox/browser/autocomplete_provider_listener.h" | 26 #include "components/omnibox/browser/autocomplete_provider_listener.h" | 
| 28 #include "components/omnibox/browser/history_url_provider.h" | 27 #include "components/omnibox/browser/history_url_provider.h" | 
| 29 #include "components/omnibox/browser/omnibox_field_trial.h" | 28 #include "components/omnibox/browser/omnibox_field_trial.h" | 
| 30 #include "components/omnibox/browser/omnibox_pref_names.h" | 29 #include "components/omnibox/browser/omnibox_pref_names.h" | 
| 31 #include "components/omnibox/browser/search_provider.h" | 30 #include "components/omnibox/browser/search_provider.h" | 
| 32 #include "components/omnibox/browser/verbatim_match.h" | 31 #include "components/omnibox/browser/verbatim_match.h" | 
| 33 #include "components/pref_registry/pref_registry_syncable.h" | 32 #include "components/pref_registry/pref_registry_syncable.h" | 
| 34 #include "components/prefs/pref_service.h" | 33 #include "components/prefs/pref_service.h" | 
| 35 #include "components/search_engines/template_url_service.h" | 34 #include "components/search_engines/template_url_service.h" | 
| 36 #include "components/url_formatter/url_formatter.h" | 35 #include "components/url_formatter/url_formatter.h" | 
| 37 #include "components/variations/net/variations_http_headers.h" | 36 #include "components/variations/net/variations_http_headers.h" | 
| 38 #include "net/base/escape.h" | 37 #include "net/base/escape.h" | 
| 39 #include "net/base/load_flags.h" | 38 #include "net/base/load_flags.h" | 
| 40 #include "net/http/http_request_headers.h" | 39 #include "net/http/http_request_headers.h" | 
| 41 #include "net/url_request/url_fetcher.h" | 40 #include "net/url_request/url_fetcher.h" | 
| 42 #include "net/url_request/url_request_status.h" | 41 #include "net/url_request/url_request_status.h" | 
| 43 #include "url/gurl.h" | 42 #include "url/gurl.h" | 
| 44 | 43 | 
| 45 namespace { | 44 namespace { | 
| 46 | 45 | 
| 47 // Represents whether ZeroSuggestProvider is allowed to display contextual |  | 
| 48 // suggestions on focus, and if not, why not. |  | 
| 49 // These values are written to logs.  New enum values can be added, but existing |  | 
| 50 // enums must never be renumbered or deleted and reused. |  | 
| 51 enum class ZeroSuggestEligibility { |  | 
| 52   ELIGIBLE = 0, |  | 
| 53   // URL_INELIGIBLE would be ELIGIBLE except some property of the current URL |  | 
| 54   // itself prevents ZeroSuggest from triggering. |  | 
| 55   URL_INELIGIBLE = 1, |  | 
| 56   GENERALLY_INELIGIBLE = 2, |  | 
| 57   ELIGIBLE_MAX_VALUE |  | 
| 58 }; |  | 
| 59 |  | 
| 60 // TODO(hfung): The histogram code was copied and modified from | 46 // TODO(hfung): The histogram code was copied and modified from | 
| 61 // search_provider.cc.  Refactor and consolidate the code. | 47 // search_provider.cc.  Refactor and consolidate the code. | 
| 62 // We keep track in a histogram how many suggest requests we send, how | 48 // We keep track in a histogram how many suggest requests we send, how | 
| 63 // many suggest requests we invalidate (e.g., due to a user typing | 49 // many suggest requests we invalidate (e.g., due to a user typing | 
| 64 // another character), and how many replies we receive. | 50 // another character), and how many replies we receive. | 
| 65 // These values are written to logs.  New enum values can be added, but existing | 51 // *** ADD NEW ENUMS AFTER ALL PREVIOUSLY DEFINED ONES! *** | 
| 66 // enums must never be renumbered or deleted and reused. | 52 //     (excluding the end-of-list enum value) | 
|  | 53 // We do not want values of existing enums to change or else it screws | 
|  | 54 // up the statistics. | 
| 67 enum ZeroSuggestRequestsHistogramValue { | 55 enum ZeroSuggestRequestsHistogramValue { | 
| 68   ZERO_SUGGEST_REQUEST_SENT = 1, | 56   ZERO_SUGGEST_REQUEST_SENT = 1, | 
| 69   ZERO_SUGGEST_REQUEST_INVALIDATED = 2, | 57   ZERO_SUGGEST_REQUEST_INVALIDATED, | 
| 70   ZERO_SUGGEST_REPLY_RECEIVED = 3, | 58   ZERO_SUGGEST_REPLY_RECEIVED, | 
| 71   ZERO_SUGGEST_MAX_REQUEST_HISTOGRAM_VALUE | 59   ZERO_SUGGEST_MAX_REQUEST_HISTOGRAM_VALUE | 
| 72 }; | 60 }; | 
| 73 | 61 | 
| 74 void LogOmniboxZeroSuggestRequest( | 62 void LogOmniboxZeroSuggestRequest( | 
| 75     ZeroSuggestRequestsHistogramValue request_value) { | 63     ZeroSuggestRequestsHistogramValue request_value) { | 
| 76   UMA_HISTOGRAM_ENUMERATION("Omnibox.ZeroSuggestRequests", request_value, | 64   UMA_HISTOGRAM_ENUMERATION("Omnibox.ZeroSuggestRequests", request_value, | 
| 77                             ZERO_SUGGEST_MAX_REQUEST_HISTOGRAM_VALUE); | 65                             ZERO_SUGGEST_MAX_REQUEST_HISTOGRAM_VALUE); | 
| 78 } | 66 } | 
| 79 | 67 | 
| 80 // Relevance value to use if it was not set explicitly by the server. | 68 // Relevance value to use if it was not set explicitly by the server. | 
| 81 const int kDefaultZeroSuggestRelevance = 100; | 69 const int kDefaultZeroSuggestRelevance = 100; | 
| 82 | 70 | 
| 83 // Used for testing whether zero suggest is ever available. |  | 
| 84 std::string kArbitraryInsecureUrlString = "http://www.google.com/"; |  | 
| 85 |  | 
| 86 }  // namespace | 71 }  // namespace | 
| 87 | 72 | 
| 88 // static | 73 // static | 
| 89 ZeroSuggestProvider* ZeroSuggestProvider::Create( | 74 ZeroSuggestProvider* ZeroSuggestProvider::Create( | 
| 90     AutocompleteProviderClient* client, | 75     AutocompleteProviderClient* client, | 
| 91     HistoryURLProvider* history_url_provider, | 76     HistoryURLProvider* history_url_provider, | 
| 92     AutocompleteProviderListener* listener) { | 77     AutocompleteProviderListener* listener) { | 
| 93   return new ZeroSuggestProvider(client, history_url_provider, listener); | 78   return new ZeroSuggestProvider(client, history_url_provider, listener); | 
| 94 } | 79 } | 
| 95 | 80 | 
| (...skipping 13 matching lines...) Expand all  Loading... | 
| 109     return; | 94     return; | 
| 110 | 95 | 
| 111   Stop(true, false); | 96   Stop(true, false); | 
| 112   set_field_trial_triggered(false); | 97   set_field_trial_triggered(false); | 
| 113   set_field_trial_triggered_in_session(false); | 98   set_field_trial_triggered_in_session(false); | 
| 114   results_from_cache_ = false; | 99   results_from_cache_ = false; | 
| 115   permanent_text_ = input.text(); | 100   permanent_text_ = input.text(); | 
| 116   current_query_ = input.current_url().spec(); | 101   current_query_ = input.current_url().spec(); | 
| 117   current_page_classification_ = input.current_page_classification(); | 102   current_page_classification_ = input.current_page_classification(); | 
| 118   current_url_match_ = MatchForCurrentURL(); | 103   current_url_match_ = MatchForCurrentURL(); | 
|  | 104   TemplateURLService* template_url_service = client()->GetTemplateURLService(); | 
| 119 | 105 | 
| 120   std::string url_string = GetContextualSuggestionsUrl(); | 106   const TemplateURL* default_provider = | 
|  | 107       template_url_service->GetDefaultSearchProvider(); | 
|  | 108   if (default_provider == NULL) | 
|  | 109     return; | 
|  | 110 | 
|  | 111   base::string16 prefix; | 
|  | 112   TemplateURLRef::SearchTermsArgs search_term_args(prefix); | 
|  | 113   std::string url_string; | 
|  | 114   if (OmniboxFieldTrial::InZeroSuggestRedirectToChromeFieldTrial()) { | 
|  | 115     url_string = OmniboxFieldTrial::ZeroSuggestRedirectToChromeServerAddress(); | 
|  | 116   } else { | 
|  | 117     url_string = default_provider->suggestions_url_ref().ReplaceSearchTerms( | 
|  | 118         search_term_args, template_url_service->search_terms_data()); | 
|  | 119   } | 
| 121   GURL suggest_url(url_string); | 120   GURL suggest_url(url_string); | 
|  | 121 | 
| 122   if (!suggest_url.is_valid()) | 122   if (!suggest_url.is_valid()) | 
| 123     return; | 123     return; | 
| 124 | 124 | 
| 125   // No need to send the current page URL in personalized suggest or | 125   // No need to send the current page URL in personalized suggest or | 
| 126   // most visited field trials. | 126   // most visited field trials. | 
| 127   const TemplateURLService* template_url_service = | 127   if (CanSendURL(input.current_url(), suggest_url, default_provider, | 
| 128       client()->GetTemplateURLService(); |  | 
| 129   const TemplateURL* default_provider = |  | 
| 130       template_url_service->GetDefaultSearchProvider(); |  | 
| 131   const bool can_send_current_url = |  | 
| 132       CanSendURL(input.current_url(), suggest_url, default_provider, |  | 
| 133                  current_page_classification_, | 128                  current_page_classification_, | 
| 134                  template_url_service->search_terms_data(), client()); | 129                  template_url_service->search_terms_data(), client()) && | 
| 135   GURL arbitrary_insecure_url(kArbitraryInsecureUrlString); |  | 
| 136   ZeroSuggestEligibility eligibility = ZeroSuggestEligibility::ELIGIBLE; |  | 
| 137   if (!can_send_current_url) { |  | 
| 138     const bool can_send_ordinary_url = |  | 
| 139         CanSendURL(arbitrary_insecure_url, suggest_url, default_provider, |  | 
| 140                    current_page_classification_, |  | 
| 141                    template_url_service->search_terms_data(), client()); |  | 
| 142     eligibility = can_send_ordinary_url |  | 
| 143                       ? ZeroSuggestEligibility::URL_INELIGIBLE |  | 
| 144                       : ZeroSuggestEligibility::GENERALLY_INELIGIBLE; |  | 
| 145   } |  | 
| 146   UMA_HISTOGRAM_ENUMERATION( |  | 
| 147       "Omnibox.ZeroSuggest.Eligible.OnFocus", static_cast<int>(eligibility), |  | 
| 148       static_cast<int>(ZeroSuggestEligibility::ELIGIBLE_MAX_VALUE)); |  | 
| 149   if (can_send_current_url && |  | 
| 150       !OmniboxFieldTrial::InZeroSuggestPersonalizedFieldTrial() && | 130       !OmniboxFieldTrial::InZeroSuggestPersonalizedFieldTrial() && | 
| 151       !OmniboxFieldTrial::InZeroSuggestMostVisitedFieldTrial()) { | 131       !OmniboxFieldTrial::InZeroSuggestMostVisitedFieldTrial()) { | 
| 152     // Update suggest_url to include the current_page_url. | 132     // Update suggest_url to include the current_page_url. | 
| 153     if (OmniboxFieldTrial::InZeroSuggestRedirectToChromeFieldTrial()) { | 133     if (OmniboxFieldTrial::InZeroSuggestRedirectToChromeFieldTrial()) { | 
| 154       url_string += | 134       url_string += | 
| 155           "/url=" + net::EscapePath(current_query_) + | 135           "/url=" + net::EscapePath(current_query_) + | 
| 156           OmniboxFieldTrial::ZeroSuggestRedirectToChromeAdditionalFields(); | 136           OmniboxFieldTrial::ZeroSuggestRedirectToChromeAdditionalFields(); | 
| 157       suggest_url = GURL(url_string); | 137       suggest_url = GURL(url_string); | 
| 158     } else { | 138     } else { | 
| 159       base::string16 prefix; |  | 
| 160       TemplateURLRef::SearchTermsArgs search_term_args(prefix); |  | 
| 161       search_term_args.current_page_url = current_query_; | 139       search_term_args.current_page_url = current_query_; | 
| 162       suggest_url = | 140       suggest_url = | 
| 163           GURL(default_provider->suggestions_url_ref().ReplaceSearchTerms( | 141           GURL(default_provider->suggestions_url_ref().ReplaceSearchTerms( | 
| 164               search_term_args, template_url_service->search_terms_data())); | 142               search_term_args, template_url_service->search_terms_data())); | 
| 165     } | 143     } | 
| 166   } else if (!ShouldShowNonContextualZeroSuggest(suggest_url, | 144   } else if (!ShouldShowNonContextualZeroSuggest(suggest_url, | 
| 167                                                  input.current_url())) { | 145                                                  input.current_url())) { | 
| 168     return; | 146     return; | 
| 169   } | 147   } | 
| 170 | 148 | 
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 224 ZeroSuggestProvider::ZeroSuggestProvider( | 202 ZeroSuggestProvider::ZeroSuggestProvider( | 
| 225     AutocompleteProviderClient* client, | 203     AutocompleteProviderClient* client, | 
| 226     HistoryURLProvider* history_url_provider, | 204     HistoryURLProvider* history_url_provider, | 
| 227     AutocompleteProviderListener* listener) | 205     AutocompleteProviderListener* listener) | 
| 228     : BaseSearchProvider(AutocompleteProvider::TYPE_ZERO_SUGGEST, client), | 206     : BaseSearchProvider(AutocompleteProvider::TYPE_ZERO_SUGGEST, client), | 
| 229       history_url_provider_(history_url_provider), | 207       history_url_provider_(history_url_provider), | 
| 230       listener_(listener), | 208       listener_(listener), | 
| 231       results_from_cache_(false), | 209       results_from_cache_(false), | 
| 232       waiting_for_most_visited_urls_request_(false), | 210       waiting_for_most_visited_urls_request_(false), | 
| 233       weak_ptr_factory_(this) { | 211       weak_ptr_factory_(this) { | 
| 234   // Record whether contextual zero suggest is possible for this user / profile. |  | 
| 235   const TemplateURLService* template_url_service = |  | 
| 236       client->GetTemplateURLService(); |  | 
| 237   // Template URL service can be null in tests. |  | 
| 238   if (template_url_service != nullptr) { |  | 
| 239     GURL suggest_url(GetContextualSuggestionsUrl()); |  | 
| 240     // To check whether this is allowed, use an arbitrary insecure (http) URL |  | 
| 241     // as the URL we'd want suggestions for.  The value of OTHER as the current |  | 
| 242     // page classification is to correspond with that URL. |  | 
| 243     UMA_HISTOGRAM_BOOLEAN( |  | 
| 244         "Omnibox.ZeroSuggest.Eligible.OnProfileOpen", |  | 
| 245         suggest_url.is_valid() && |  | 
| 246             CanSendURL(GURL(kArbitraryInsecureUrlString), suggest_url, |  | 
| 247                        template_url_service->GetDefaultSearchProvider(), |  | 
| 248                        metrics::OmniboxEventProto::OTHER, |  | 
| 249                        template_url_service->search_terms_data(), client)); |  | 
| 250   } |  | 
| 251 } | 212 } | 
| 252 | 213 | 
| 253 ZeroSuggestProvider::~ZeroSuggestProvider() { | 214 ZeroSuggestProvider::~ZeroSuggestProvider() { | 
| 254 } | 215 } | 
| 255 | 216 | 
| 256 const TemplateURL* ZeroSuggestProvider::GetTemplateURL(bool is_keyword) const { | 217 const TemplateURL* ZeroSuggestProvider::GetTemplateURL(bool is_keyword) const { | 
| 257   // Zero suggest provider should not receive keyword results. | 218   // Zero suggest provider should not receive keyword results. | 
| 258   DCHECK(!is_keyword); | 219   DCHECK(!is_keyword); | 
| 259   return client()->GetTemplateURLService()->GetDefaultSearchProvider(); | 220   return client()->GetTemplateURLService()->GetDefaultSearchProvider(); | 
| 260 } | 221 } | 
| (...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 511 | 472 | 
| 512   if (OmniboxFieldTrial::InZeroSuggestMostVisitedWithoutSerpFieldTrial() && | 473   if (OmniboxFieldTrial::InZeroSuggestMostVisitedWithoutSerpFieldTrial() && | 
| 513       client() | 474       client() | 
| 514           ->GetTemplateURLService() | 475           ->GetTemplateURLService() | 
| 515           ->IsSearchResultsPageFromDefaultSearchProvider(current_page_url)) | 476           ->IsSearchResultsPageFromDefaultSearchProvider(current_page_url)) | 
| 516     return false; | 477     return false; | 
| 517 | 478 | 
| 518   return true; | 479   return true; | 
| 519 } | 480 } | 
| 520 | 481 | 
| 521 std::string ZeroSuggestProvider::GetContextualSuggestionsUrl() const { |  | 
| 522   // Without a default search provider, refuse to do anything (even if the user |  | 
| 523   // is in the redirect-to-chrome field trial). |  | 
| 524   const TemplateURLService* template_url_service = |  | 
| 525       client()->GetTemplateURLService(); |  | 
| 526   const TemplateURL* default_provider = |  | 
| 527       template_url_service->GetDefaultSearchProvider(); |  | 
| 528   if (default_provider == nullptr) |  | 
| 529     return std::string(); |  | 
| 530 |  | 
| 531   if (OmniboxFieldTrial::InZeroSuggestRedirectToChromeFieldTrial()) |  | 
| 532     return OmniboxFieldTrial::ZeroSuggestRedirectToChromeServerAddress(); |  | 
| 533   base::string16 prefix; |  | 
| 534   TemplateURLRef::SearchTermsArgs search_term_args(prefix); |  | 
| 535   return default_provider->suggestions_url_ref().ReplaceSearchTerms( |  | 
| 536       search_term_args, template_url_service->search_terms_data()); |  | 
| 537 } |  | 
| 538 |  | 
| 539 void ZeroSuggestProvider::MaybeUseCachedSuggestions() { | 482 void ZeroSuggestProvider::MaybeUseCachedSuggestions() { | 
| 540   if (!OmniboxFieldTrial::InZeroSuggestPersonalizedFieldTrial()) | 483   if (!OmniboxFieldTrial::InZeroSuggestPersonalizedFieldTrial()) | 
| 541     return; | 484     return; | 
| 542 | 485 | 
| 543   std::string json_data = | 486   std::string json_data = | 
| 544       client()->GetPrefs()->GetString(omnibox::kZeroSuggestCachedResults); | 487       client()->GetPrefs()->GetString(omnibox::kZeroSuggestCachedResults); | 
| 545   if (!json_data.empty()) { | 488   if (!json_data.empty()) { | 
| 546     std::unique_ptr<base::Value> data( | 489     std::unique_ptr<base::Value> data( | 
| 547         SearchSuggestionParser::DeserializeJsonData(json_data)); | 490         SearchSuggestionParser::DeserializeJsonData(json_data)); | 
| 548     if (data && ParseSuggestResults( | 491     if (data && ParseSuggestResults( | 
| 549             *data, kDefaultZeroSuggestRelevance, false, &results_)) { | 492             *data, kDefaultZeroSuggestRelevance, false, &results_)) { | 
| 550       ConvertResultsToAutocompleteMatches(); | 493       ConvertResultsToAutocompleteMatches(); | 
| 551       results_from_cache_ = !matches_.empty(); | 494       results_from_cache_ = !matches_.empty(); | 
| 552     } | 495     } | 
| 553   } | 496   } | 
| 554 } | 497 } | 
| OLD | NEW | 
|---|