Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(115)

Side by Side Diff: components/ntp_snippets/ntp_snippets_service.cc

Issue 1737563003: [NTP Snippets] Persist the set of snippets in a pref (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@snippets_merge
Patch Set: noyau review Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 "base/files/file_path.h" 7 #include "base/files/file_path.h"
8 #include "base/files/file_util.h" 8 #include "base/files/file_util.h"
9 #include "base/json/json_reader.h" 9 #include "base/json/json_reader.h"
10 #include "base/location.h" 10 #include "base/location.h"
11 #include "base/path_service.h" 11 #include "base/path_service.h"
12 #include "base/task_runner_util.h" 12 #include "base/task_runner_util.h"
13 #include "base/values.h" 13 #include "base/values.h"
14 #include "components/ntp_snippets/pref_names.h"
15 #include "components/pref_registry/pref_registry_syncable.h"
16 #include "components/prefs/pref_service.h"
14 17
15 namespace { 18 namespace {
16 19
17 // TODO(crbug.com/587857): This is an extremely small value, for development. 20 // TODO(crbug.com/587857): This is an extremely small value, for development.
18 // Replace it by something sensible and add a command line param to control it. 21 // Replace it by something sensible and add a command line param to control it.
19 const int kDefaultFetchingIntervalSeconds = 60; 22 const int kDefaultFetchingIntervalSeconds = 60;
20 23
21 bool ReadFileToString(const base::FilePath& path, std::string* data) { 24 bool ReadFileToString(const base::FilePath& path, std::string* data) {
22 DCHECK(data); 25 DCHECK(data);
23 bool success = base::ReadFileToString(path, data); 26 bool success = base::ReadFileToString(path, data);
24 DLOG_IF(ERROR, !success) << "Error reading file " << path.LossyDisplayName(); 27 DLOG_IF(ERROR, !success) << "Error reading file " << path.LossyDisplayName();
25 return success; 28 return success;
26 } 29 }
27 30
31 const char kContentInfo[] = "contentInfo";
32
28 } // namespace 33 } // namespace
29 34
30 namespace ntp_snippets { 35 namespace ntp_snippets {
31 36
32 NTPSnippetsService::NTPSnippetsService( 37 NTPSnippetsService::NTPSnippetsService(
38 PrefService* pref_service,
33 scoped_refptr<base::SequencedTaskRunner> file_task_runner, 39 scoped_refptr<base::SequencedTaskRunner> file_task_runner,
34 const std::string& application_language_code, 40 const std::string& application_language_code,
35 NTPSnippetsScheduler* scheduler, 41 NTPSnippetsScheduler* scheduler,
36 scoped_ptr<NTPSnippetsFetcher> snippets_fetcher) 42 scoped_ptr<NTPSnippetsFetcher> snippets_fetcher)
37 : loaded_(false), 43 : pref_service_(pref_service),
44 loaded_(false),
38 file_task_runner_(file_task_runner), 45 file_task_runner_(file_task_runner),
39 application_language_code_(application_language_code), 46 application_language_code_(application_language_code),
40 scheduler_(scheduler), 47 scheduler_(scheduler),
41 snippets_fetcher_(std::move(snippets_fetcher)), 48 snippets_fetcher_(std::move(snippets_fetcher)),
42 weak_ptr_factory_(this) { 49 weak_ptr_factory_(this) {
43 snippets_fetcher_callback_ = snippets_fetcher_->AddCallback( 50 snippets_fetcher_callback_ = snippets_fetcher_->AddCallback(
44 base::Bind(&NTPSnippetsService::OnSnippetsDownloaded, 51 base::Bind(&NTPSnippetsService::OnSnippetsDownloaded,
45 weak_ptr_factory_.GetWeakPtr())); 52 weak_ptr_factory_.GetWeakPtr()));
46 } 53 }
47 54
48 NTPSnippetsService::~NTPSnippetsService() {} 55 NTPSnippetsService::~NTPSnippetsService() {}
49 56
57 // static
58 void NTPSnippetsService::RegisterProfilePrefs(
59 user_prefs::PrefRegistrySyncable* registry) {
60 registry->RegisterListPref(prefs::kSnippets);
61 }
62
50 void NTPSnippetsService::Init(bool enabled) { 63 void NTPSnippetsService::Init(bool enabled) {
51 // If enabled, get snippets immediately. If we've downloaded them before, 64 // If enabled, get any existing snippets immediately from prefs.
52 // this will just read from disk. 65 if (enabled) {
53 if (enabled) 66 LoadFromPrefs();
54 FetchSnippets(false); 67
68 // If we don't have any snippets yet, start a fetch.
69 if (snippets_.empty())
70 FetchSnippets(false);
71 }
55 72
56 // The scheduler only exists on Android so far, it's null on other platforms. 73 // The scheduler only exists on Android so far, it's null on other platforms.
57 if (!scheduler_) 74 if (!scheduler_)
58 return; 75 return;
59 76
60 if (enabled) 77 if (enabled)
61 scheduler_->Schedule(kDefaultFetchingIntervalSeconds); 78 scheduler_->Schedule(kDefaultFetchingIntervalSeconds);
62 else 79 else
63 scheduler_->Unschedule(); 80 scheduler_->Unschedule();
64 } 81 }
(...skipping 11 matching lines...) Expand all
76 void NTPSnippetsService::AddObserver(NTPSnippetsServiceObserver* observer) { 93 void NTPSnippetsService::AddObserver(NTPSnippetsServiceObserver* observer) {
77 observers_.AddObserver(observer); 94 observers_.AddObserver(observer);
78 if (loaded_) 95 if (loaded_)
79 observer->NTPSnippetsServiceLoaded(this); 96 observer->NTPSnippetsServiceLoaded(this);
80 } 97 }
81 98
82 void NTPSnippetsService::RemoveObserver(NTPSnippetsServiceObserver* observer) { 99 void NTPSnippetsService::RemoveObserver(NTPSnippetsServiceObserver* observer) {
83 observers_.RemoveObserver(observer); 100 observers_.RemoveObserver(observer);
84 } 101 }
85 102
103 void NTPSnippetsService::OnSnippetsDownloaded(
104 const base::FilePath& download_path) {
105 std::string* downloaded_data = new std::string;
106 base::PostTaskAndReplyWithResult(
107 file_task_runner_.get(), FROM_HERE,
108 base::Bind(&ReadFileToString, download_path, downloaded_data),
109 base::Bind(&NTPSnippetsService::OnFileReadDone,
110 weak_ptr_factory_.GetWeakPtr(), base::Owned(downloaded_data)));
111 }
112
86 void NTPSnippetsService::OnFileReadDone(const std::string* json, bool success) { 113 void NTPSnippetsService::OnFileReadDone(const std::string* json, bool success) {
87 if (!success) 114 if (!success)
88 return; 115 return;
89 116
90 DCHECK(json); 117 DCHECK(json);
91 LoadFromJSONString(*json); 118 LoadFromJSONString(*json);
119 StoreToPrefs();
92 } 120 }
93 121
94 bool NTPSnippetsService::LoadFromJSONString(const std::string& str) { 122 bool NTPSnippetsService::LoadFromJSONString(const std::string& str) {
95 scoped_ptr<base::Value> deserialized = base::JSONReader::Read(str); 123 scoped_ptr<base::Value> deserialized = base::JSONReader::Read(str);
96 if (!deserialized) 124 if (!deserialized)
97 return false; 125 return false;
98 126
99 const base::DictionaryValue* top_dict = nullptr; 127 const base::DictionaryValue* top_dict = nullptr;
100 if (!deserialized->GetAsDictionary(&top_dict)) 128 if (!deserialized->GetAsDictionary(&top_dict))
101 return false; 129 return false;
102 130
103 const base::ListValue* list = nullptr; 131 const base::ListValue* list = nullptr;
104 if (!top_dict->GetList("recos", &list)) 132 if (!top_dict->GetList("recos", &list))
105 return false; 133 return false;
106 134
107 for (const base::Value* const value : *list) { 135 return LoadFromJSONList(*list);
136 }
137
138 bool NTPSnippetsService::LoadFromJSONList(const base::ListValue& list) {
139 for (const base::Value* const value : list) {
108 const base::DictionaryValue* dict = nullptr; 140 const base::DictionaryValue* dict = nullptr;
109 if (!value->GetAsDictionary(&dict)) 141 if (!value->GetAsDictionary(&dict))
110 return false; 142 return false;
111 143
112 const base::DictionaryValue* content = nullptr; 144 const base::DictionaryValue* content = nullptr;
113 if (!dict->GetDictionary("contentInfo", &content)) 145 if (!dict->GetDictionary(kContentInfo, &content))
114 return false; 146 return false;
115 scoped_ptr<NTPSnippet> snippet = 147 scoped_ptr<NTPSnippet> snippet = NTPSnippet::CreateFromDictionary(*content);
116 NTPSnippet::NTPSnippetFromDictionary(*content);
117 if (!snippet) 148 if (!snippet)
118 return false; 149 return false;
119 150
120 // Check if we already have a snippet with the same URL. If so, replace it 151 // Check if we already have a snippet with the same URL. If so, replace it
121 // rather than adding a duplicate. 152 // rather than adding a duplicate.
122 const GURL& url = snippet->url(); 153 const GURL& url = snippet->url();
123 auto it = std::find_if(snippets_.begin(), snippets_.end(), 154 auto it = std::find_if(snippets_.begin(), snippets_.end(),
124 [&url](const scoped_ptr<NTPSnippet>& old_snippet) { 155 [&url](const scoped_ptr<NTPSnippet>& old_snippet) {
125 return old_snippet->url() == url; 156 return old_snippet->url() == url;
126 }); 157 });
127 if (it != snippets_.end()) 158 if (it != snippets_.end())
128 *it = std::move(snippet); 159 *it = std::move(snippet);
129 else 160 else
130 snippets_.push_back(std::move(snippet)); 161 snippets_.push_back(std::move(snippet));
131 } 162 }
132 loaded_ = true; 163 loaded_ = true;
133 164
134 FOR_EACH_OBSERVER(NTPSnippetsServiceObserver, observers_, 165 FOR_EACH_OBSERVER(NTPSnippetsServiceObserver, observers_,
135 NTPSnippetsServiceLoaded(this)); 166 NTPSnippetsServiceLoaded(this));
136 return true; 167 return true;
137 } 168 }
138 169
139 void NTPSnippetsService::OnSnippetsDownloaded( 170 void NTPSnippetsService::LoadFromPrefs() {
140 const base::FilePath& download_path) { 171 // |pref_service_| can be null in tests.
141 std::string* downloaded_data = new std::string; 172 if (!pref_service_)
142 base::PostTaskAndReplyWithResult( 173 return;
143 file_task_runner_.get(), FROM_HERE, 174 if (!LoadFromJSONList(*pref_service_->GetList(prefs::kSnippets)))
144 base::Bind(&ReadFileToString, download_path, downloaded_data), 175 LOG(ERROR) << "Failed to parse snippets from prefs";
145 base::Bind(&NTPSnippetsService::OnFileReadDone, 176 }
146 weak_ptr_factory_.GetWeakPtr(), base::Owned(downloaded_data))); 177
178 void NTPSnippetsService::StoreToPrefs() {
179 // |pref_service_| can be null in tests.
180 if (!pref_service_)
181 return;
182 base::ListValue list;
183 for (const auto& snippet : snippets_) {
184 scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue);
185 dict->Set(kContentInfo, snippet->ToDictionary());
186 list.Append(std::move(dict));
187 }
188 pref_service_->Set(prefs::kSnippets, list);
147 } 189 }
148 190
149 } // namespace ntp_snippets 191 } // namespace ntp_snippets
OLDNEW
« no previous file with comments | « components/ntp_snippets/ntp_snippets_service.h ('k') | components/ntp_snippets/ntp_snippets_service_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698