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