Chromium Code Reviews| Index: components/ntp_snippets/ntp_snippets_service.cc |
| diff --git a/components/ntp_snippets/ntp_snippets_service.cc b/components/ntp_snippets/ntp_snippets_service.cc |
| index c696405d82fc58ec56c79ca21a2d7ced803a2938..88eda32e87db682fcb1d001c74f5f992ff227daa 100644 |
| --- a/components/ntp_snippets/ntp_snippets_service.cc |
| +++ b/components/ntp_snippets/ntp_snippets_service.cc |
| @@ -6,11 +6,14 @@ |
| #include "base/files/file_path.h" |
| #include "base/files/file_util.h" |
| -#include "base/json/json_string_value_serializer.h" |
| +#include "base/json/json_reader.h" |
| #include "base/location.h" |
| #include "base/path_service.h" |
| #include "base/task_runner_util.h" |
| #include "base/values.h" |
| +#include "components/ntp_snippets/pref_names.h" |
| +#include "components/pref_registry/pref_registry_syncable.h" |
| +#include "components/prefs/pref_service.h" |
| namespace { |
| @@ -30,11 +33,13 @@ bool ReadFileToString(const base::FilePath& path, std::string* data) { |
| namespace ntp_snippets { |
| NTPSnippetsService::NTPSnippetsService( |
| + PrefService* pref_service, |
| scoped_refptr<base::SequencedTaskRunner> file_task_runner, |
| const std::string& application_language_code, |
| NTPSnippetsScheduler* scheduler, |
| scoped_ptr<NTPSnippetsFetcher> snippets_fetcher) |
| - : loaded_(false), |
| + : pref_service_(pref_service), |
| + loaded_(false), |
| file_task_runner_(file_task_runner), |
| application_language_code_(application_language_code), |
| scheduler_(scheduler), |
| @@ -47,11 +52,21 @@ NTPSnippetsService::NTPSnippetsService( |
| NTPSnippetsService::~NTPSnippetsService() {} |
| +// static |
| +void NTPSnippetsService::RegisterProfilePrefs( |
| + user_prefs::PrefRegistrySyncable* registry) { |
| + registry->RegisterListPref(prefs::kSnippets); |
| +} |
| + |
| void NTPSnippetsService::Init(bool enabled) { |
| - // If enabled, get snippets immediately. If we've downloaded them before, |
| - // this will just read from disk. |
| - if (enabled) |
| - FetchSnippets(false); |
| + // If enabled, get any existing snippets immediately from prefs. |
| + if (enabled) { |
| + LoadFromPrefs(); |
| + |
| + // If we don't have any snippets yet, start a fetch. |
| + if (snippets_.empty()) |
| + FetchSnippets(false); |
| + } |
| // The scheduler only exists on Android so far, it's null on other platforms. |
| if (!scheduler_) |
| @@ -83,47 +98,64 @@ void NTPSnippetsService::RemoveObserver(NTPSnippetsServiceObserver* observer) { |
| observers_.RemoveObserver(observer); |
| } |
| +void NTPSnippetsService::OnSnippetsDownloaded( |
| + const base::FilePath& download_path) { |
| + std::string* downloaded_data = new std::string; |
| + base::PostTaskAndReplyWithResult( |
| + file_task_runner_.get(), FROM_HERE, |
| + base::Bind(&ReadFileToString, download_path, downloaded_data), |
| + base::Bind(&NTPSnippetsService::OnFileReadDone, |
| + weak_ptr_factory_.GetWeakPtr(), base::Owned(downloaded_data))); |
| +} |
| + |
| void NTPSnippetsService::OnFileReadDone(const std::string* json, bool success) { |
| if (!success) |
| return; |
| DCHECK(json); |
| LoadFromJSONString(*json); |
| + StoreToPrefs(); |
| } |
| bool NTPSnippetsService::LoadFromJSONString(const std::string& str) { |
| - snippets_.clear(); |
| - |
| - JSONStringValueDeserializer deserializer(str); |
| - int error_code; |
| - std::string error_message; |
| - |
| - scoped_ptr<base::Value> deserialized = |
| - deserializer.Deserialize(&error_code, &error_message); |
| + scoped_ptr<base::Value> deserialized = base::JSONReader::Read(str); |
| if (!deserialized) |
| return false; |
| - const base::DictionaryValue* top_dict = NULL; |
| + const base::DictionaryValue* top_dict = nullptr; |
| if (!deserialized->GetAsDictionary(&top_dict)) |
| return false; |
| - const base::ListValue* list = NULL; |
| + const base::ListValue* list = nullptr; |
| if (!top_dict->GetList("recos", &list)) |
| return false; |
| - for (base::Value* const value : *list) { |
| - const base::DictionaryValue* dict = NULL; |
| + return LoadFromJSONList(*list); |
| +} |
| + |
| +bool NTPSnippetsService::LoadFromJSONList(const base::ListValue& list) { |
| + for (const base::Value* const value : list) { |
| + const base::DictionaryValue* dict = nullptr; |
| if (!value->GetAsDictionary(&dict)) |
| return false; |
| - const base::DictionaryValue* content = NULL; |
| + const base::DictionaryValue* content = nullptr; |
| if (!dict->GetDictionary("contentInfo", &content)) |
| return false; |
| - scoped_ptr<NTPSnippet> snippet = |
| - NTPSnippet::NTPSnippetFromDictionary(*content); |
| + scoped_ptr<NTPSnippet> snippet = NTPSnippet::CreateFromDictionary(*content); |
| if (!snippet) |
| return false; |
| - snippets_.push_back(std::move(snippet)); |
| + // Check if we already have a snippet with the same URL. If so, replace it |
| + // rather than adding a duplicate. |
| + const GURL& url = snippet->url(); |
| + auto it = std::find_if(snippets_.begin(), snippets_.end(), |
| + [&url](const scoped_ptr<NTPSnippet>& old_snippet) { |
| + return old_snippet->url() == url; |
| + }); |
| + if (it != snippets_.end()) |
| + *it = std::move(snippet); |
| + else |
| + snippets_.push_back(std::move(snippet)); |
| } |
| loaded_ = true; |
| @@ -132,14 +164,25 @@ bool NTPSnippetsService::LoadFromJSONString(const std::string& str) { |
| return true; |
| } |
| -void NTPSnippetsService::OnSnippetsDownloaded( |
| - const base::FilePath& download_path) { |
| - std::string* downloaded_data = new std::string; |
| - base::PostTaskAndReplyWithResult( |
| - file_task_runner_.get(), FROM_HERE, |
| - base::Bind(&ReadFileToString, download_path, downloaded_data), |
| - base::Bind(&NTPSnippetsService::OnFileReadDone, |
| - weak_ptr_factory_.GetWeakPtr(), base::Owned(downloaded_data))); |
| +void NTPSnippetsService::LoadFromPrefs() { |
| + // |pref_service_| can be null in tests. |
| + if (!pref_service_) |
| + return; |
| + if (!LoadFromJSONList(*pref_service_->GetList(prefs::kSnippets))) |
| + LOG(ERROR) << "Failed to parse " << prefs::kSnippets << " pref"; |
|
Bernhard Bauer
2016/02/26 17:30:48
Nit: printing the value of the pref key is not goi
Marc Treib
2016/02/29 10:04:42
Done.
|
| +} |
| + |
| +void NTPSnippetsService::StoreToPrefs() { |
| + // |pref_service_| can be null in tests. |
| + if (!pref_service_) |
| + return; |
| + base::ListValue list; |
| + for (const auto& snippet : snippets_) { |
| + scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue); |
| + dict->Set("contentInfo", snippet->ToDictionary()); |
| + list.Append(std::move(dict)); |
| + } |
| + pref_service_->Set(prefs::kSnippets, list); |
| } |
| } // namespace ntp_snippets |