| 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/ntp_snippets_service.h" | 5 #include "components/ntp_snippets/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" | 12 #include "base/files/file_path.h" |
| 13 #include "base/files/file_util.h" | 13 #include "base/files/file_util.h" |
| 14 #include "base/json/json_reader.h" | 14 #include "base/json/json_reader.h" |
| 15 #include "base/location.h" | 15 #include "base/location.h" |
| 16 #include "base/path_service.h" | 16 #include "base/path_service.h" |
| 17 #include "base/strings/string_number_conversions.h" | 17 #include "base/strings/string_number_conversions.h" |
| 18 #include "base/strings/stringprintf.h" |
| 18 #include "base/task_runner_util.h" | 19 #include "base/task_runner_util.h" |
| 19 #include "base/time/time.h" | 20 #include "base/time/time.h" |
| 20 #include "base/values.h" | 21 #include "base/values.h" |
| 21 #include "components/ntp_snippets/pref_names.h" | 22 #include "components/ntp_snippets/pref_names.h" |
| 22 #include "components/ntp_snippets/switches.h" | 23 #include "components/ntp_snippets/switches.h" |
| 23 #include "components/prefs/pref_registry_simple.h" | 24 #include "components/prefs/pref_registry_simple.h" |
| 24 #include "components/prefs/pref_service.h" | 25 #include "components/prefs/pref_service.h" |
| 25 #include "components/suggestions/proto/suggestions.pb.h" | 26 #include "components/suggestions/proto/suggestions.pb.h" |
| 26 | 27 |
| 27 using suggestions::ChromeSuggestion; | 28 using suggestions::ChromeSuggestion; |
| 28 using suggestions::SuggestionsProfile; | 29 using suggestions::SuggestionsProfile; |
| 29 using suggestions::SuggestionsService; | 30 using suggestions::SuggestionsService; |
| 30 | 31 |
| 31 namespace ntp_snippets { | 32 namespace ntp_snippets { |
| 32 | 33 |
| 33 namespace { | 34 namespace { |
| 34 | 35 |
| 35 const int kFetchingIntervalWifiChargingSeconds = 30 * 60; | 36 const int kFetchingIntervalWifiChargingSeconds = 30 * 60; |
| 36 const int kFetchingIntervalWifiSeconds = 2 * 60 * 60; | 37 const int kFetchingIntervalWifiSeconds = 2 * 60 * 60; |
| 37 const int kFetchingIntervalFallbackSeconds = 24 * 60 * 60; | 38 const int kFetchingIntervalFallbackSeconds = 24 * 60 * 60; |
| 38 | 39 |
| 39 // These define the times of day during which we will fetch via Wifi (without | 40 // These define the times of day during which we will fetch via Wifi (without |
| 40 // charging) - 6 AM to 10 PM. | 41 // charging) - 6 AM to 10 PM. |
| 41 const int kWifiFetchingHourMin = 6; | 42 const int kWifiFetchingHourMin = 6; |
| 42 const int kWifiFetchingHourMax = 22; | 43 const int kWifiFetchingHourMax = 22; |
| 43 | 44 |
| 44 const int kDefaultExpiryTimeMins = 24 * 60; | 45 const int kDefaultExpiryTimeMins = 24 * 60; |
| 45 | 46 |
| 47 const char kStatusMessageEmptyHosts[] = "Cannot fetch for empty hosts list."; |
| 48 const char kStatusMessageEmptyList[] = "Invalid / empty list."; |
| 49 const char kStatusMessageJsonErrorFormat[] = "Received invalid JSON (error %s)"; |
| 50 const char kStatusMessageOK[] = "OK"; |
| 51 |
| 46 base::TimeDelta GetFetchingInterval(const char* switch_name, | 52 base::TimeDelta GetFetchingInterval(const char* switch_name, |
| 47 int default_value_seconds) { | 53 int default_value_seconds) { |
| 48 int value_seconds = default_value_seconds; | 54 int value_seconds = default_value_seconds; |
| 49 const base::CommandLine& cmdline = *base::CommandLine::ForCurrentProcess(); | 55 const base::CommandLine& cmdline = *base::CommandLine::ForCurrentProcess(); |
| 50 if (cmdline.HasSwitch(switch_name)) { | 56 if (cmdline.HasSwitch(switch_name)) { |
| 51 std::string str = cmdline.GetSwitchValueASCII(switch_name); | 57 std::string str = cmdline.GetSwitchValueASCII(switch_name); |
| 52 int switch_value_seconds = 0; | 58 int switch_value_seconds = 0; |
| 53 if (base::StringToInt(str, &switch_value_seconds)) | 59 if (base::StringToInt(str, &switch_value_seconds)) |
| 54 value_seconds = switch_value_seconds; | 60 value_seconds = switch_value_seconds; |
| 55 else | 61 else |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 225 FetchSnippetsFromHosts(GetSuggestionsHosts()); | 231 FetchSnippetsFromHosts(GetSuggestionsHosts()); |
| 226 } | 232 } |
| 227 | 233 |
| 228 void NTPSnippetsService::FetchSnippetsFromHosts( | 234 void NTPSnippetsService::FetchSnippetsFromHosts( |
| 229 const std::set<std::string>& hosts) { | 235 const std::set<std::string>& hosts) { |
| 230 if (base::CommandLine::ForCurrentProcess()->HasSwitch( | 236 if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 231 switches::kDontRestrict)) { | 237 switches::kDontRestrict)) { |
| 232 snippets_fetcher_->FetchSnippets(std::set<std::string>()); | 238 snippets_fetcher_->FetchSnippets(std::set<std::string>()); |
| 233 return; | 239 return; |
| 234 } | 240 } |
| 235 if (!hosts.empty()) | 241 if (!hosts.empty()) { |
| 236 snippets_fetcher_->FetchSnippets(hosts); | 242 snippets_fetcher_->FetchSnippets(hosts); |
| 243 } else { |
| 244 last_fetch_status_ = kStatusMessageEmptyHosts; |
| 245 LoadingSnippetsFinished(); |
| 246 } |
| 237 } | 247 } |
| 238 | 248 |
| 239 void NTPSnippetsService::RescheduleFetching() { | 249 void NTPSnippetsService::RescheduleFetching() { |
| 240 // The scheduler only exists on Android so far, it's null on other platforms. | 250 // The scheduler only exists on Android so far, it's null on other platforms. |
| 241 if (!scheduler_) | 251 if (!scheduler_) |
| 242 return; | 252 return; |
| 243 | 253 |
| 244 if (enabled_) { | 254 if (enabled_) { |
| 245 base::Time now = base::Time::Now(); | 255 base::Time now = base::Time::Now(); |
| 246 scheduler_->Schedule( | 256 scheduler_->Schedule( |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 317 StoreSnippetsToPrefs(); | 327 StoreSnippetsToPrefs(); |
| 318 StoreSnippetHostsToPrefs(hosts); | 328 StoreSnippetHostsToPrefs(hosts); |
| 319 | 329 |
| 320 FOR_EACH_OBSERVER(NTPSnippetsServiceObserver, observers_, | 330 FOR_EACH_OBSERVER(NTPSnippetsServiceObserver, observers_, |
| 321 NTPSnippetsServiceLoaded()); | 331 NTPSnippetsServiceLoaded()); |
| 322 | 332 |
| 323 FetchSnippetsFromHosts(hosts); | 333 FetchSnippetsFromHosts(hosts); |
| 324 } | 334 } |
| 325 | 335 |
| 326 void NTPSnippetsService::OnSnippetsDownloaded( | 336 void NTPSnippetsService::OnSnippetsDownloaded( |
| 327 const std::string& snippets_json) { | 337 const std::string& snippets_json, const std::string& status) { |
| 328 parse_json_callback_.Run( | 338 |
| 329 snippets_json, base::Bind(&NTPSnippetsService::OnJsonParsed, | 339 if (!snippets_json.empty()) { |
| 330 weak_ptr_factory_.GetWeakPtr(), snippets_json), | 340 DCHECK(status.empty()); |
| 331 base::Bind(&NTPSnippetsService::OnJsonError, | 341 |
| 332 weak_ptr_factory_.GetWeakPtr(), snippets_json)); | 342 parse_json_callback_.Run( |
| 343 snippets_json, |
| 344 base::Bind(&NTPSnippetsService::OnJsonParsed, |
| 345 weak_ptr_factory_.GetWeakPtr(), snippets_json), |
| 346 base::Bind(&NTPSnippetsService::OnJsonError, |
| 347 weak_ptr_factory_.GetWeakPtr(), snippets_json)); |
| 348 } else { |
| 349 last_fetch_status_ = status; |
| 350 LoadingSnippetsFinished(); |
| 351 } |
| 333 } | 352 } |
| 334 | 353 |
| 335 void NTPSnippetsService::OnJsonParsed(const std::string& snippets_json, | 354 void NTPSnippetsService::OnJsonParsed(const std::string& snippets_json, |
| 336 scoped_ptr<base::Value> parsed) { | 355 scoped_ptr<base::Value> parsed) { |
| 337 LOG_IF(WARNING, !LoadFromValue(*parsed)) << "Received invalid snippets: " | 356 if (!LoadFromValue(*parsed)) { |
| 338 << snippets_json; | 357 LOG(WARNING) << "Received invalid snippets: " << snippets_json; |
| 358 last_fetch_status_ = kStatusMessageEmptyList; |
| 359 } else { |
| 360 last_fetch_status_ = kStatusMessageOK; |
| 361 } |
| 362 |
| 363 LoadingSnippetsFinished(); |
| 339 } | 364 } |
| 340 | 365 |
| 341 void NTPSnippetsService::OnJsonError(const std::string& snippets_json, | 366 void NTPSnippetsService::OnJsonError(const std::string& snippets_json, |
| 342 const std::string& error) { | 367 const std::string& error) { |
| 343 LOG(WARNING) << "Received invalid JSON (" << error << "): " << snippets_json; | 368 LOG(WARNING) << "Received invalid JSON (" << error << "): " << snippets_json; |
| 369 last_fetch_status_ = base::StringPrintf(kStatusMessageJsonErrorFormat, |
| 370 error.c_str()); |
| 371 |
| 372 LoadingSnippetsFinished(); |
| 344 } | 373 } |
| 345 | 374 |
| 346 bool NTPSnippetsService::LoadFromValue(const base::Value& value) { | 375 bool NTPSnippetsService::LoadFromValue(const base::Value& value) { |
| 347 const base::DictionaryValue* top_dict = nullptr; | 376 const base::DictionaryValue* top_dict = nullptr; |
| 348 if (!value.GetAsDictionary(&top_dict)) | 377 if (!value.GetAsDictionary(&top_dict)) |
| 349 return false; | 378 return false; |
| 350 | 379 |
| 351 const base::ListValue* list = nullptr; | 380 const base::ListValue* list = nullptr; |
| 352 if (!top_dict->GetList("recos", &list)) | 381 if (!top_dict->GetList("recos", &list)) |
| 353 return false; | 382 return false; |
| (...skipping 24 matching lines...) Expand all Loading... |
| 378 snippet->publish_date() + | 407 snippet->publish_date() + |
| 379 base::TimeDelta::FromMinutes(kDefaultExpiryTimeMins)); | 408 base::TimeDelta::FromMinutes(kDefaultExpiryTimeMins)); |
| 380 } | 409 } |
| 381 } | 410 } |
| 382 | 411 |
| 383 // Insert the new snippets at the front. | 412 // Insert the new snippets at the front. |
| 384 snippets_.insert(snippets_.begin(), | 413 snippets_.insert(snippets_.begin(), |
| 385 std::make_move_iterator(new_snippets.begin()), | 414 std::make_move_iterator(new_snippets.begin()), |
| 386 std::make_move_iterator(new_snippets.end())); | 415 std::make_move_iterator(new_snippets.end())); |
| 387 | 416 |
| 388 // Immediately remove any already-expired snippets. This will also notify our | |
| 389 // observers and schedule the expiry timer. | |
| 390 RemoveExpiredSnippets(); | |
| 391 | |
| 392 return true; | 417 return true; |
| 393 } | 418 } |
| 394 | 419 |
| 395 void NTPSnippetsService::LoadSnippetsFromPrefs() { | 420 void NTPSnippetsService::LoadSnippetsFromPrefs() { |
| 396 bool success = LoadFromListValue(*pref_service_->GetList(prefs::kSnippets)); | 421 bool success = LoadFromListValue(*pref_service_->GetList(prefs::kSnippets)); |
| 397 DCHECK(success) << "Failed to parse snippets from prefs"; | 422 DCHECK(success) << "Failed to parse snippets from prefs"; |
| 423 |
| 424 LoadingSnippetsFinished(); |
| 398 } | 425 } |
| 399 | 426 |
| 400 void NTPSnippetsService::StoreSnippetsToPrefs() { | 427 void NTPSnippetsService::StoreSnippetsToPrefs() { |
| 401 pref_service_->Set(prefs::kSnippets, *SnippetsToListValue(snippets_)); | 428 pref_service_->Set(prefs::kSnippets, *SnippetsToListValue(snippets_)); |
| 402 } | 429 } |
| 403 | 430 |
| 404 void NTPSnippetsService::LoadDiscardedSnippetsFromPrefs() { | 431 void NTPSnippetsService::LoadDiscardedSnippetsFromPrefs() { |
| 405 discarded_snippets_.clear(); | 432 discarded_snippets_.clear(); |
| 406 bool success = AddSnippetsFromListValue( | 433 bool success = AddSnippetsFromListValue( |
| 407 *pref_service_->GetList(prefs::kDiscardedSnippets), | 434 *pref_service_->GetList(prefs::kDiscardedSnippets), |
| (...skipping 19 matching lines...) Expand all Loading... |
| 427 } | 454 } |
| 428 | 455 |
| 429 void NTPSnippetsService::StoreSnippetHostsToPrefs( | 456 void NTPSnippetsService::StoreSnippetHostsToPrefs( |
| 430 const std::set<std::string>& hosts) { | 457 const std::set<std::string>& hosts) { |
| 431 base::ListValue list; | 458 base::ListValue list; |
| 432 for (const std::string& host : hosts) | 459 for (const std::string& host : hosts) |
| 433 list.AppendString(host); | 460 list.AppendString(host); |
| 434 pref_service_->Set(prefs::kSnippetHosts, list); | 461 pref_service_->Set(prefs::kSnippetHosts, list); |
| 435 } | 462 } |
| 436 | 463 |
| 437 void NTPSnippetsService::RemoveExpiredSnippets() { | 464 void NTPSnippetsService::LoadingSnippetsFinished() { |
| 465 // Remove expired snippets. |
| 438 base::Time expiry = base::Time::Now(); | 466 base::Time expiry = base::Time::Now(); |
| 439 | 467 |
| 440 snippets_.erase( | 468 snippets_.erase( |
| 441 std::remove_if(snippets_.begin(), snippets_.end(), | 469 std::remove_if(snippets_.begin(), snippets_.end(), |
| 442 [&expiry](const scoped_ptr<NTPSnippet>& snippet) { | 470 [&expiry](const scoped_ptr<NTPSnippet>& snippet) { |
| 443 return snippet->expiry_date() <= expiry; | 471 return snippet->expiry_date() <= expiry; |
| 444 }), | 472 }), |
| 445 snippets_.end()); | 473 snippets_.end()); |
| 446 StoreSnippetsToPrefs(); | 474 StoreSnippetsToPrefs(); |
| 447 | 475 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 464 for (const auto& snippet : snippets_) { | 492 for (const auto& snippet : snippets_) { |
| 465 if (snippet->expiry_date() < next_expiry) | 493 if (snippet->expiry_date() < next_expiry) |
| 466 next_expiry = snippet->expiry_date(); | 494 next_expiry = snippet->expiry_date(); |
| 467 } | 495 } |
| 468 for (const auto& snippet : discarded_snippets_) { | 496 for (const auto& snippet : discarded_snippets_) { |
| 469 if (snippet->expiry_date() < next_expiry) | 497 if (snippet->expiry_date() < next_expiry) |
| 470 next_expiry = snippet->expiry_date(); | 498 next_expiry = snippet->expiry_date(); |
| 471 } | 499 } |
| 472 DCHECK_GT(next_expiry, expiry); | 500 DCHECK_GT(next_expiry, expiry); |
| 473 expiry_timer_.Start(FROM_HERE, next_expiry - expiry, | 501 expiry_timer_.Start(FROM_HERE, next_expiry - expiry, |
| 474 base::Bind(&NTPSnippetsService::RemoveExpiredSnippets, | 502 base::Bind(&NTPSnippetsService::LoadingSnippetsFinished, |
| 475 base::Unretained(this))); | 503 base::Unretained(this))); |
| 476 } | 504 } |
| 477 | 505 |
| 478 } // namespace ntp_snippets | 506 } // namespace ntp_snippets |
| OLD | NEW |