| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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/ntp_snippets/remote/ntp_snippets_service.h" | 5 #include "components/ntp_snippets/remote/ntp_snippets_service.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <iterator> | 8 #include <iterator> |
| 9 #include <utility> | 9 #include <utility> |
| 10 | 10 |
| 11 #include "base/command_line.h" | 11 #include "base/command_line.h" |
| 12 #include "base/files/file_path.h" | |
| 13 #include "base/files/file_util.h" | |
| 14 #include "base/location.h" | 12 #include "base/location.h" |
| 15 #include "base/metrics/histogram_macros.h" | 13 #include "base/metrics/histogram_macros.h" |
| 16 #include "base/metrics/sparse_histogram.h" | 14 #include "base/metrics/sparse_histogram.h" |
| 17 #include "base/path_service.h" | 15 #include "base/path_service.h" |
| 18 #include "base/stl_util.h" | 16 #include "base/stl_util.h" |
| 19 #include "base/strings/string_number_conversions.h" | 17 #include "base/strings/string_number_conversions.h" |
| 20 #include "base/strings/utf_string_conversions.h" | 18 #include "base/strings/utf_string_conversions.h" |
| 21 #include "base/task_runner_util.h" | 19 #include "base/task_runner_util.h" |
| 22 #include "base/time/time.h" | 20 #include "base/time/time.h" |
| 23 #include "base/values.h" | 21 #include "base/values.h" |
| 24 #include "components/data_use_measurement/core/data_use_user_data.h" | 22 #include "components/data_use_measurement/core/data_use_user_data.h" |
| 25 #include "components/history/core/browser/history_service.h" | 23 #include "components/history/core/browser/history_service.h" |
| 26 #include "components/image_fetcher/image_decoder.h" | 24 #include "components/image_fetcher/image_decoder.h" |
| 27 #include "components/image_fetcher/image_fetcher.h" | 25 #include "components/image_fetcher/image_fetcher.h" |
| 28 #include "components/ntp_snippets/ntp_snippets_constants.h" | 26 #include "components/ntp_snippets/features.h" |
| 29 #include "components/ntp_snippets/pref_names.h" | 27 #include "components/ntp_snippets/pref_names.h" |
| 30 #include "components/ntp_snippets/remote/ntp_snippets_database.h" | 28 #include "components/ntp_snippets/remote/ntp_snippets_database.h" |
| 31 #include "components/ntp_snippets/switches.h" | 29 #include "components/ntp_snippets/switches.h" |
| 30 #include "components/ntp_snippets/user_classifier.h" |
| 32 #include "components/prefs/pref_registry_simple.h" | 31 #include "components/prefs/pref_registry_simple.h" |
| 33 #include "components/prefs/pref_service.h" | 32 #include "components/prefs/pref_service.h" |
| 34 #include "components/suggestions/proto/suggestions.pb.h" | 33 #include "components/suggestions/proto/suggestions.pb.h" |
| 35 #include "components/variations/variations_associated_data.h" | 34 #include "components/variations/variations_associated_data.h" |
| 36 #include "grit/components_strings.h" | 35 #include "grit/components_strings.h" |
| 37 #include "ui/base/l10n/l10n_util.h" | 36 #include "ui/base/l10n/l10n_util.h" |
| 38 #include "ui/gfx/image/image.h" | 37 #include "ui/gfx/image/image.h" |
| 39 | 38 |
| 40 using image_fetcher::ImageDecoder; | 39 using image_fetcher::ImageDecoder; |
| 41 using image_fetcher::ImageFetcher; | 40 using image_fetcher::ImageFetcher; |
| 42 using suggestions::ChromeSuggestion; | 41 using suggestions::ChromeSuggestion; |
| 43 using suggestions::SuggestionsProfile; | 42 using suggestions::SuggestionsProfile; |
| 44 using suggestions::SuggestionsService; | 43 using suggestions::SuggestionsService; |
| 45 | 44 |
| 46 namespace ntp_snippets { | 45 namespace ntp_snippets { |
| 47 | 46 |
| 48 namespace { | 47 namespace { |
| 49 | 48 |
| 50 // Number of snippets requested to the server. Consider replacing sparse UMA | 49 // Number of snippets requested to the server. Consider replacing sparse UMA |
| 51 // histograms with COUNTS() if this number increases beyond 50. | 50 // histograms with COUNTS() if this number increases beyond 50. |
| 52 const int kMaxSnippetCount = 10; | 51 const int kMaxSnippetCount = 10; |
| 53 | 52 |
| 54 // Number of archived snippets we keep around in memory. | 53 // Number of archived snippets we keep around in memory. |
| 55 const int kMaxArchivedSnippetCount = 200; | 54 const int kMaxArchivedSnippetCount = 200; |
| 56 | 55 |
| 57 // Default values for snippets fetching intervals - once per day only. | 56 // Default values for fetching intervals, fallback and wifi. |
| 58 const int kDefaultFetchingIntervalWifiSeconds = 0; | 57 const double kDefaultFetchingIntervalRareNtpUser[] = {48.0, 24.0}; |
| 59 const int kDefaultFetchingIntervalFallbackSeconds = 24 * 60 * 60; | 58 const double kDefaultFetchingIntervalActiveNtpUser[] = {24.0, 6.0}; |
| 59 const double kDefaultFetchingIntervalActiveSuggestionsConsumer[] = {24.0, 6.0}; |
| 60 | 60 |
| 61 // Variation parameters than can override the default fetching intervals. | 61 // Variation parameters than can override the default fetching intervals. |
| 62 const char kFetchingIntervalWifiParamName[] = | 62 const char* kFetchingIntervalParamNameRareNtpUser[] = { |
| 63 "fetching_interval_wifi_seconds"; | 63 "fetching_interval_hours-fallback-rare_ntp_user", |
| 64 const char kFetchingIntervalFallbackParamName[] = | 64 "fetching_interval_hours-wifi-rare_ntp_user"}; |
| 65 "fetching_interval_fallback_seconds"; | 65 const char* kFetchingIntervalParamNameActiveNtpUser[] = { |
| 66 "fetching_interval_hours-fallback-active_ntp_user", |
| 67 "fetching_interval_hours-wifi-active_ntp_user"}; |
| 68 const char* kFetchingIntervalParamNameActiveSuggestionsConsumer[] = { |
| 69 "fetching_interval_hours-fallback-active_suggestions_consumer", |
| 70 "fetching_interval_hours-wifi-active_suggestions_consumer"}; |
| 66 | 71 |
| 67 const int kDefaultExpiryTimeMins = 3 * 24 * 60; | 72 const int kDefaultExpiryTimeMins = 3 * 24 * 60; |
| 68 | 73 |
| 69 base::TimeDelta GetFetchingInterval(const char* switch_name, | 74 base::TimeDelta GetFetchingInterval(bool is_wifi, |
| 70 const char* param_name, | 75 UserClassifier::UserClass user_class) { |
| 71 int default_value_seconds) { | 76 double value_hours = 0.0; |
| 72 int value_seconds = default_value_seconds; | 77 |
| 78 const int index = is_wifi ? 1 : 0; |
| 79 const char* param_name = ""; |
| 80 switch (user_class) { |
| 81 case UserClassifier::UserClass::RARE_NTP_USER: |
| 82 value_hours = kDefaultFetchingIntervalRareNtpUser[index]; |
| 83 param_name = kFetchingIntervalParamNameRareNtpUser[index]; |
| 84 break; |
| 85 case UserClassifier::UserClass::ACTIVE_NTP_USER: |
| 86 value_hours = kDefaultFetchingIntervalActiveNtpUser[index]; |
| 87 param_name = kFetchingIntervalParamNameActiveNtpUser[index]; |
| 88 break; |
| 89 case UserClassifier::UserClass::ACTIVE_SUGGESTIONS_CONSUMER: |
| 90 value_hours = kDefaultFetchingIntervalActiveSuggestionsConsumer[index]; |
| 91 param_name = kFetchingIntervalParamNameActiveSuggestionsConsumer[index]; |
| 92 break; |
| 93 } |
| 73 | 94 |
| 74 // The default value can be overridden by a variation parameter. | 95 // The default value can be overridden by a variation parameter. |
| 75 // TODO(treib,jkrcal): Use GetVariationParamValueByFeature and get rid of | 96 std::string param_value_str = variations::GetVariationParamValueByFeature( |
| 76 // kStudyName, also in NTPSnippetsFetcher. | 97 ntp_snippets::kArticleSuggestionsFeature, param_name); |
| 77 std::string param_value_str = variations::GetVariationParamValue( | |
| 78 ntp_snippets::kStudyName, param_name); | |
| 79 if (!param_value_str.empty()) { | 98 if (!param_value_str.empty()) { |
| 80 int param_value_seconds = 0; | 99 double param_value_hours = 0.0; |
| 81 if (base::StringToInt(param_value_str, ¶m_value_seconds)) | 100 if (base::StringToDouble(param_value_str, ¶m_value_hours)) |
| 82 value_seconds = param_value_seconds; | 101 value_hours = param_value_hours; |
| 83 else | 102 else |
| 84 LOG(WARNING) << "Invalid value for variation parameter " << param_name; | 103 LOG(WARNING) << "Invalid value for variation parameter " << param_name; |
| 85 } | 104 } |
| 86 | 105 |
| 87 // A value from the command line parameter overrides anything else. | 106 return base::TimeDelta::FromSecondsD(value_hours * 3600.0); |
| 88 const base::CommandLine& cmdline = *base::CommandLine::ForCurrentProcess(); | |
| 89 if (cmdline.HasSwitch(switch_name)) { | |
| 90 std::string str = cmdline.GetSwitchValueASCII(switch_name); | |
| 91 int switch_value_seconds = 0; | |
| 92 if (base::StringToInt(str, &switch_value_seconds)) | |
| 93 value_seconds = switch_value_seconds; | |
| 94 else | |
| 95 LOG(WARNING) << "Invalid value for switch " << switch_name; | |
| 96 } | |
| 97 return base::TimeDelta::FromSeconds(value_seconds); | |
| 98 } | |
| 99 | |
| 100 base::TimeDelta GetFetchingIntervalWifi() { | |
| 101 return GetFetchingInterval(switches::kFetchingIntervalWifiSeconds, | |
| 102 kFetchingIntervalWifiParamName, | |
| 103 kDefaultFetchingIntervalWifiSeconds); | |
| 104 } | |
| 105 | |
| 106 base::TimeDelta GetFetchingIntervalFallback() { | |
| 107 return GetFetchingInterval(switches::kFetchingIntervalFallbackSeconds, | |
| 108 kFetchingIntervalFallbackParamName, | |
| 109 kDefaultFetchingIntervalFallbackSeconds); | |
| 110 } | 107 } |
| 111 | 108 |
| 112 // Extracts the hosts from |suggestions| and returns them in a set. | 109 // Extracts the hosts from |suggestions| and returns them in a set. |
| 113 std::set<std::string> GetSuggestionsHostsImpl( | 110 std::set<std::string> GetSuggestionsHostsImpl( |
| 114 const SuggestionsProfile& suggestions) { | 111 const SuggestionsProfile& suggestions) { |
| 115 std::set<std::string> hosts; | 112 std::set<std::string> hosts; |
| 116 for (int i = 0; i < suggestions.suggestions_size(); ++i) { | 113 for (int i = 0; i < suggestions.suggestions_size(); ++i) { |
| 117 const ChromeSuggestion& suggestion = suggestions.suggestions(i); | 114 const ChromeSuggestion& suggestion = suggestions.suggestions(i); |
| 118 GURL url(suggestion.url()); | 115 GURL url(suggestion.url()); |
| 119 if (url.is_valid()) | 116 if (url.is_valid()) |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 175 } | 172 } |
| 176 | 173 |
| 177 } // namespace | 174 } // namespace |
| 178 | 175 |
| 179 NTPSnippetsService::NTPSnippetsService( | 176 NTPSnippetsService::NTPSnippetsService( |
| 180 Observer* observer, | 177 Observer* observer, |
| 181 CategoryFactory* category_factory, | 178 CategoryFactory* category_factory, |
| 182 PrefService* pref_service, | 179 PrefService* pref_service, |
| 183 SuggestionsService* suggestions_service, | 180 SuggestionsService* suggestions_service, |
| 184 const std::string& application_language_code, | 181 const std::string& application_language_code, |
| 182 const UserClassifier* user_classifier, |
| 185 NTPSnippetsScheduler* scheduler, | 183 NTPSnippetsScheduler* scheduler, |
| 186 std::unique_ptr<NTPSnippetsFetcher> snippets_fetcher, | 184 std::unique_ptr<NTPSnippetsFetcher> snippets_fetcher, |
| 187 std::unique_ptr<ImageFetcher> image_fetcher, | 185 std::unique_ptr<ImageFetcher> image_fetcher, |
| 188 std::unique_ptr<ImageDecoder> image_decoder, | 186 std::unique_ptr<ImageDecoder> image_decoder, |
| 189 std::unique_ptr<NTPSnippetsDatabase> database, | 187 std::unique_ptr<NTPSnippetsDatabase> database, |
| 190 std::unique_ptr<NTPSnippetsStatusService> status_service) | 188 std::unique_ptr<NTPSnippetsStatusService> status_service) |
| 191 : ContentSuggestionsProvider(observer, category_factory), | 189 : ContentSuggestionsProvider(observer, category_factory), |
| 192 state_(State::NOT_INITED), | 190 state_(State::NOT_INITED), |
| 193 pref_service_(pref_service), | 191 pref_service_(pref_service), |
| 194 suggestions_service_(suggestions_service), | 192 suggestions_service_(suggestions_service), |
| 195 articles_category_( | 193 articles_category_( |
| 196 category_factory->FromKnownCategory(KnownCategories::ARTICLES)), | 194 category_factory->FromKnownCategory(KnownCategories::ARTICLES)), |
| 197 application_language_code_(application_language_code), | 195 application_language_code_(application_language_code), |
| 196 user_classifier_(user_classifier), |
| 198 scheduler_(scheduler), | 197 scheduler_(scheduler), |
| 199 snippets_fetcher_(std::move(snippets_fetcher)), | 198 snippets_fetcher_(std::move(snippets_fetcher)), |
| 200 image_fetcher_(std::move(image_fetcher)), | 199 image_fetcher_(std::move(image_fetcher)), |
| 201 image_decoder_(std::move(image_decoder)), | 200 image_decoder_(std::move(image_decoder)), |
| 202 database_(std::move(database)), | 201 database_(std::move(database)), |
| 203 snippets_status_service_(std::move(status_service)), | 202 snippets_status_service_(std::move(status_service)), |
| 204 fetch_when_ready_(false), | 203 fetch_when_ready_(false), |
| 205 nuke_when_initialized_(false), | 204 nuke_when_initialized_(false), |
| 206 thumbnail_requests_throttler_( | 205 thumbnail_requests_throttler_( |
| 207 pref_service, | 206 pref_service, |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 276 if (!scheduler_) | 275 if (!scheduler_) |
| 277 return; | 276 return; |
| 278 | 277 |
| 279 if (ready()) { | 278 if (ready()) { |
| 280 base::TimeDelta old_interval_wifi = | 279 base::TimeDelta old_interval_wifi = |
| 281 base::TimeDelta::FromInternalValue(pref_service_->GetInt64( | 280 base::TimeDelta::FromInternalValue(pref_service_->GetInt64( |
| 282 prefs::kSnippetBackgroundFetchingIntervalWifi)); | 281 prefs::kSnippetBackgroundFetchingIntervalWifi)); |
| 283 base::TimeDelta old_interval_fallback = | 282 base::TimeDelta old_interval_fallback = |
| 284 base::TimeDelta::FromInternalValue(pref_service_->GetInt64( | 283 base::TimeDelta::FromInternalValue(pref_service_->GetInt64( |
| 285 prefs::kSnippetBackgroundFetchingIntervalFallback)); | 284 prefs::kSnippetBackgroundFetchingIntervalFallback)); |
| 286 base::TimeDelta interval_wifi = GetFetchingIntervalWifi(); | 285 UserClassifier::UserClass user_class = user_classifier_->GetUserClass(); |
| 287 base::TimeDelta interval_fallback = GetFetchingIntervalFallback(); | 286 base::TimeDelta interval_wifi = |
| 287 GetFetchingInterval(/*is_wifi=*/true, user_class); |
| 288 base::TimeDelta interval_fallback = |
| 289 GetFetchingInterval(/*is_wifi=*/false, user_class); |
| 288 if (force || interval_wifi != old_interval_wifi || | 290 if (force || interval_wifi != old_interval_wifi || |
| 289 interval_fallback != old_interval_fallback) { | 291 interval_fallback != old_interval_fallback) { |
| 290 scheduler_->Schedule(interval_wifi, interval_fallback); | 292 scheduler_->Schedule(interval_wifi, interval_fallback); |
| 291 pref_service_->SetInt64(prefs::kSnippetBackgroundFetchingIntervalWifi, | 293 pref_service_->SetInt64(prefs::kSnippetBackgroundFetchingIntervalWifi, |
| 292 interval_wifi.ToInternalValue()); | 294 interval_wifi.ToInternalValue()); |
| 293 pref_service_->SetInt64( | 295 pref_service_->SetInt64( |
| 294 prefs::kSnippetBackgroundFetchingIntervalFallback, | 296 prefs::kSnippetBackgroundFetchingIntervalFallback, |
| 295 interval_fallback.ToInternalValue()); | 297 interval_fallback.ToInternalValue()); |
| 296 } | 298 } |
| 297 } else { | 299 } else { |
| 298 // If we're NOT_INITED, we don't know whether to schedule or un-schedule. | 300 // If we're NOT_INITED, we don't know whether to schedule or unschedule. |
| 299 // If |force| is false, all is well: We'll reschedule on the next state | 301 // If |force| is false, all is well: We'll reschedule on the next state |
| 300 // change anyway. If it's true, then unschedule here, to make sure that the | 302 // change anyway. If it's true, then unschedule here, to make sure that the |
| 301 // next reschedule actually happens. | 303 // next reschedule actually happens. |
| 302 if (state_ != State::NOT_INITED || force) { | 304 if (state_ != State::NOT_INITED || force) { |
| 303 scheduler_->Unschedule(); | 305 scheduler_->Unschedule(); |
| 304 pref_service_->ClearPref(prefs::kSnippetBackgroundFetchingIntervalWifi); | 306 pref_service_->ClearPref(prefs::kSnippetBackgroundFetchingIntervalWifi); |
| 305 pref_service_->ClearPref( | 307 pref_service_->ClearPref( |
| 306 prefs::kSnippetBackgroundFetchingIntervalFallback); | 308 prefs::kSnippetBackgroundFetchingIntervalFallback); |
| 307 } | 309 } |
| 308 } | 310 } |
| (...skipping 352 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 661 | 663 |
| 662 // Fill in default publish/expiry dates where required. | 664 // Fill in default publish/expiry dates where required. |
| 663 for (std::unique_ptr<NTPSnippet>& snippet : new_snippets) { | 665 for (std::unique_ptr<NTPSnippet>& snippet : new_snippets) { |
| 664 if (snippet->publish_date().is_null()) | 666 if (snippet->publish_date().is_null()) |
| 665 snippet->set_publish_date(base::Time::Now()); | 667 snippet->set_publish_date(base::Time::Now()); |
| 666 if (snippet->expiry_date().is_null()) { | 668 if (snippet->expiry_date().is_null()) { |
| 667 snippet->set_expiry_date( | 669 snippet->set_expiry_date( |
| 668 snippet->publish_date() + | 670 snippet->publish_date() + |
| 669 base::TimeDelta::FromMinutes(kDefaultExpiryTimeMins)); | 671 base::TimeDelta::FromMinutes(kDefaultExpiryTimeMins)); |
| 670 } | 672 } |
| 671 | |
| 672 // TODO(treib): Prefetch and cache the snippet image. crbug.com/605870 | |
| 673 } | 673 } |
| 674 | 674 |
| 675 if (!base::CommandLine::ForCurrentProcess()->HasSwitch( | 675 if (!base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 676 switches::kAddIncompleteSnippets)) { | 676 switches::kAddIncompleteSnippets)) { |
| 677 int num_new_snippets = new_snippets.size(); | 677 int num_new_snippets = new_snippets.size(); |
| 678 // Remove snippets that do not have all the info we need to display it to | 678 // Remove snippets that do not have all the info we need to display it to |
| 679 // the user. | 679 // the user. |
| 680 new_snippets.erase( | 680 new_snippets.erase( |
| 681 std::remove_if(new_snippets.begin(), new_snippets.end(), | 681 std::remove_if(new_snippets.begin(), new_snippets.end(), |
| 682 [](const std::unique_ptr<NTPSnippet>& snippet) { | 682 [](const std::unique_ptr<NTPSnippet>& snippet) { |
| (...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1062 } | 1062 } |
| 1063 | 1063 |
| 1064 NTPSnippetsService::CategoryContent::CategoryContent() = default; | 1064 NTPSnippetsService::CategoryContent::CategoryContent() = default; |
| 1065 NTPSnippetsService::CategoryContent::CategoryContent(CategoryContent&&) = | 1065 NTPSnippetsService::CategoryContent::CategoryContent(CategoryContent&&) = |
| 1066 default; | 1066 default; |
| 1067 NTPSnippetsService::CategoryContent::~CategoryContent() = default; | 1067 NTPSnippetsService::CategoryContent::~CategoryContent() = default; |
| 1068 NTPSnippetsService::CategoryContent& NTPSnippetsService::CategoryContent:: | 1068 NTPSnippetsService::CategoryContent& NTPSnippetsService::CategoryContent:: |
| 1069 operator=(CategoryContent&&) = default; | 1069 operator=(CategoryContent&&) = default; |
| 1070 | 1070 |
| 1071 } // namespace ntp_snippets | 1071 } // namespace ntp_snippets |
| OLD | NEW |