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

Side by Side Diff: chrome/browser/android/ntp/popular_sites.cc

Issue 1957313003: Remove PopularSites' dependencies on //chrome/.... (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 7 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 "chrome/browser/android/ntp/popular_sites.h" 5 #include "chrome/browser/android/ntp/popular_sites.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
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/path_service.h"
15 #include "base/strings/string_util.h" 14 #include "base/strings/string_util.h"
16 #include "base/strings/stringprintf.h" 15 #include "base/strings/stringprintf.h"
17 #include "base/task_runner_util.h" 16 #include "base/task_runner_util.h"
18 #include "base/time/time.h" 17 #include "base/time/time.h"
19 #include "base/values.h" 18 #include "base/values.h"
20 #include "chrome/common/chrome_paths.h"
21 #include "components/google/core/browser/google_util.h" 19 #include "components/google/core/browser/google_util.h"
22 #include "components/ntp_tiles/pref_names.h" 20 #include "components/ntp_tiles/pref_names.h"
23 #include "components/ntp_tiles/switches.h" 21 #include "components/ntp_tiles/switches.h"
24 #include "components/pref_registry/pref_registry_syncable.h" 22 #include "components/pref_registry/pref_registry_syncable.h"
25 #include "components/prefs/pref_service.h" 23 #include "components/prefs/pref_service.h"
24 #include "components/safe_json/json_sanitizer.h"
26 #include "components/search_engines/search_engine_type.h" 25 #include "components/search_engines/search_engine_type.h"
27 #include "components/search_engines/template_url_prepopulate_data.h" 26 #include "components/search_engines/template_url_prepopulate_data.h"
28 #include "components/search_engines/template_url_service.h" 27 #include "components/search_engines/template_url_service.h"
29 #include "components/variations/service/variations_service.h" 28 #include "components/variations/service/variations_service.h"
30 #include "content/public/browser/browser_thread.h" 29 #include "content/public/browser/browser_thread.h"
30 #include "net/base/load_flags.h"
31 #include "net/http/http_status_code.h"
31 32
32 using content::BrowserThread; 33 using content::BrowserThread;
34 using net::URLFetcher;
33 using variations::VariationsService; 35 using variations::VariationsService;
34 36
35 namespace { 37 namespace {
36 38
37 const char kPopularSitesURLFormat[] = 39 const char kPopularSitesURLFormat[] =
38 "https://www.gstatic.com/chrome/ntp/suggested_sites_%s_%s.json"; 40 "https://www.gstatic.com/chrome/ntp/suggested_sites_%s_%s.json";
39 const char kPopularSitesDefaultCountryCode[] = "DEFAULT"; 41 const char kPopularSitesDefaultCountryCode[] = "DEFAULT";
40 const char kPopularSitesDefaultVersion[] = "5"; 42 const char kPopularSitesDefaultVersion[] = "5";
41 const char kPopularSitesLocalFilename[] = "suggested_sites.json"; 43 const char kPopularSitesLocalFilename[] = "suggested_sites.json";
42 const int kPopularSitesRedownloadIntervalHours = 24; 44 const int kPopularSitesRedownloadIntervalHours = 24;
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
116 118
117 if (version.empty()) 119 if (version.empty())
118 version = variation_param_version; 120 version = variation_param_version;
119 121
120 if (version.empty()) 122 if (version.empty())
121 version = kPopularSitesDefaultVersion; 123 version = kPopularSitesDefaultVersion;
122 124
123 return version; 125 return version;
124 } 126 }
125 127
126 base::FilePath GetPopularSitesPath() { 128 std::unique_ptr<std::vector<PopularSites::Site>> ParseJsonFile(
Marc Treib 2016/05/10 08:32:43 Just ParseJson now? Not a file anymore at this poi
sfiera 2016/05/11 09:00:24 Done.
127 base::FilePath dir; 129 const std::string& json) {
128 PathService::Get(chrome::DIR_USER_DATA, &dir);
129 return dir.AppendASCII(kPopularSitesLocalFilename);
130 }
131
132 std::unique_ptr<std::vector<PopularSites::Site>> ReadAndParseJsonFile(
133 const base::FilePath& path) {
134 std::string json;
135 if (!base::ReadFileToString(path, &json)) {
136 DLOG(WARNING) << "Failed reading file";
137 return nullptr;
138 }
139
140 std::unique_ptr<base::Value> value = 130 std::unique_ptr<base::Value> value =
141 base::JSONReader::Read(json, base::JSON_ALLOW_TRAILING_COMMAS); 131 base::JSONReader::Read(json, base::JSON_ALLOW_TRAILING_COMMAS);
142 base::ListValue* list; 132 base::ListValue* list;
143 if (!value || !value->GetAsList(&list)) { 133 if (!value || !value->GetAsList(&list)) {
144 DLOG(WARNING) << "Failed parsing json"; 134 DLOG(WARNING) << "Failed parsing json";
145 return nullptr; 135 return nullptr;
146 } 136 }
147 137
148 std::unique_ptr<std::vector<PopularSites::Site>> sites( 138 std::unique_ptr<std::vector<PopularSites::Site>> sites(
149 new std::vector<PopularSites::Site>); 139 new std::vector<PopularSites::Site>);
(...skipping 13 matching lines...) Expand all
163 item->GetString("large_icon_url", &large_icon_url); 153 item->GetString("large_icon_url", &large_icon_url);
164 154
165 sites->push_back(PopularSites::Site(title, GURL(url), GURL(favicon_url), 155 sites->push_back(PopularSites::Site(title, GURL(url), GURL(favicon_url),
166 GURL(large_icon_url), 156 GURL(large_icon_url),
167 GURL(thumbnail_url))); 157 GURL(thumbnail_url)));
168 } 158 }
169 159
170 return sites; 160 return sites;
171 } 161 }
172 162
163 // Write |data| to a temporary file, then move it to |path|, thereby ensuring
164 // that a partial file cannot be written.
165 //
166 // TODO(sfiera): is there some helper for this somewhere?
Marc Treib 2016/05/10 08:32:43 Not that I'm aware.
sfiera 2016/05/11 09:00:24 Well.
167 bool WriteStringToFileAtomic(const std::string& data,
168 const base::FilePath& path) {
169 base::FilePath temporary_path;
170 return base::CreateTemporaryFile(&temporary_path) &&
171 base::WriteFile(temporary_path, data.data(), data.size()) &&
172 base::Move(temporary_path, path);
173 }
174
173 } // namespace 175 } // namespace
174 176
175 PopularSites::Site::Site(const base::string16& title, 177 PopularSites::Site::Site(const base::string16& title,
176 const GURL& url, 178 const GURL& url,
177 const GURL& favicon_url, 179 const GURL& favicon_url,
178 const GURL& large_icon_url, 180 const GURL& large_icon_url,
179 const GURL& thumbnail_url) 181 const GURL& thumbnail_url)
180 : title(title), 182 : title(title),
181 url(url), 183 url(url),
182 favicon_url(favicon_url), 184 favicon_url(favicon_url),
183 large_icon_url(large_icon_url), 185 large_icon_url(large_icon_url),
184 thumbnail_url(thumbnail_url) {} 186 thumbnail_url(thumbnail_url) {}
185 187
186 PopularSites::Site::Site(const Site& other) = default; 188 PopularSites::Site::Site(const Site& other) = default;
187 189
188 PopularSites::Site::~Site() {} 190 PopularSites::Site::~Site() {}
189 191
190 PopularSites::PopularSites(PrefService* prefs, 192 PopularSites::PopularSites(PrefService* prefs,
191 const TemplateURLService* template_url_service, 193 const TemplateURLService* template_url_service,
192 VariationsService* variations_service, 194 VariationsService* variations_service,
193 net::URLRequestContextGetter* download_context, 195 net::URLRequestContextGetter* download_context,
196 const base::FilePath& directory,
194 const std::string& variation_param_country, 197 const std::string& variation_param_country,
195 const std::string& variation_param_version, 198 const std::string& variation_param_version,
196 bool force_download, 199 bool force_download,
197 const FinishedCallback& callback) 200 const FinishedCallback& callback)
198 : PopularSites(prefs, 201 : PopularSites(prefs,
199 template_url_service, 202 template_url_service,
200 download_context, 203 download_context,
204 directory,
201 GetCountryToUse(prefs, 205 GetCountryToUse(prefs,
202 template_url_service, 206 template_url_service,
203 variations_service, 207 variations_service,
204 variation_param_country), 208 variation_param_country),
205 GetVersionToUse(prefs, variation_param_version), 209 GetVersionToUse(prefs, variation_param_version),
206 GURL(), 210 GURL(),
207 force_download, 211 force_download,
208 callback) {} 212 callback) {}
209 213
210 PopularSites::PopularSites(PrefService* prefs, 214 PopularSites::PopularSites(PrefService* prefs,
211 const TemplateURLService* template_url_service, 215 const TemplateURLService* template_url_service,
212 net::URLRequestContextGetter* download_context, 216 net::URLRequestContextGetter* download_context,
217 const base::FilePath& directory,
213 const GURL& url, 218 const GURL& url,
214 const FinishedCallback& callback) 219 const FinishedCallback& callback)
215 : PopularSites(prefs, 220 : PopularSites(prefs,
216 template_url_service, 221 template_url_service,
217 download_context, 222 download_context,
223 directory,
218 std::string(), 224 std::string(),
219 std::string(), 225 std::string(),
220 url, 226 url,
221 true, 227 true,
222 callback) {} 228 callback) {}
223 229
224 PopularSites::~PopularSites() {} 230 PopularSites::~PopularSites() {}
225 231
226 std::string PopularSites::GetCountry() const { 232 std::string PopularSites::GetCountry() const {
227 return prefs_->GetString(kPopularSitesCountryPref); 233 return prefs_->GetString(kPopularSitesCountryPref);
(...skipping 12 matching lines...) Expand all
240 std::string()); 246 std::string());
241 247
242 user_prefs->RegisterInt64Pref(kPopularSitesLastDownloadPref, 0); 248 user_prefs->RegisterInt64Pref(kPopularSitesLastDownloadPref, 0);
243 user_prefs->RegisterStringPref(kPopularSitesCountryPref, std::string()); 249 user_prefs->RegisterStringPref(kPopularSitesCountryPref, std::string());
244 user_prefs->RegisterStringPref(kPopularSitesVersionPref, std::string()); 250 user_prefs->RegisterStringPref(kPopularSitesVersionPref, std::string());
245 } 251 }
246 252
247 PopularSites::PopularSites(PrefService* prefs, 253 PopularSites::PopularSites(PrefService* prefs,
248 const TemplateURLService* template_url_service, 254 const TemplateURLService* template_url_service,
249 net::URLRequestContextGetter* download_context, 255 net::URLRequestContextGetter* download_context,
256 const base::FilePath& directory,
250 const std::string& country, 257 const std::string& country,
251 const std::string& version, 258 const std::string& version,
252 const GURL& override_url, 259 const GURL& override_url,
253 bool force_download, 260 bool force_download,
254 const FinishedCallback& callback) 261 const FinishedCallback& callback)
255 : callback_(callback), 262 : callback_(callback),
256 pending_country_(country), 263 pending_country_(country),
257 pending_version_(version), 264 pending_version_(version),
258 local_path_(GetPopularSitesPath()), 265 local_path_(directory.empty()
266 ? base::FilePath()
267 : directory.AppendASCII(kPopularSitesLocalFilename)),
259 prefs_(prefs), 268 prefs_(prefs),
260 template_url_service_(template_url_service), 269 template_url_service_(template_url_service),
261 download_context_(download_context), 270 download_context_(download_context),
262 weak_ptr_factory_(this) { 271 weak_ptr_factory_(this) {
263 const base::Time last_download_time = base::Time::FromInternalValue( 272 const base::Time last_download_time = base::Time::FromInternalValue(
264 prefs_->GetInt64(kPopularSitesLastDownloadPref)); 273 prefs_->GetInt64(kPopularSitesLastDownloadPref));
265 const base::TimeDelta time_since_last_download = 274 const base::TimeDelta time_since_last_download =
266 base::Time::Now() - last_download_time; 275 base::Time::Now() - last_download_time;
267 const base::TimeDelta redownload_interval = 276 const base::TimeDelta redownload_interval =
268 base::TimeDelta::FromHours(kPopularSitesRedownloadIntervalHours); 277 base::TimeDelta::FromHours(kPopularSitesRedownloadIntervalHours);
269 const bool download_time_is_future = base::Time::Now() < last_download_time; 278 const bool download_time_is_future = base::Time::Now() < last_download_time;
270 const bool country_changed = GetCountry() != pending_country_; 279 const bool country_changed = GetCountry() != pending_country_;
271 const bool version_changed = GetVersion() != pending_version_; 280 const bool version_changed = GetVersion() != pending_version_;
272 281
273 const bool should_redownload_if_exists = 282 const bool should_redownload_if_exists =
274 force_download || download_time_is_future || 283 force_download || download_time_is_future ||
275 (time_since_last_download > redownload_interval) || country_changed || 284 (time_since_last_download > redownload_interval) || country_changed ||
276 version_changed; 285 version_changed;
277 286
287 if (local_path_.empty()) {
288 BrowserThread::GetBlockingPool()
289 ->GetTaskRunnerWithShutdownBehavior(
290 base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN)
291 ->PostTask(FROM_HERE, base::Bind(callback_, false));
Marc Treib 2016/05/10 08:32:43 Why are you posting the callback to another thread
sfiera 2016/05/11 09:00:24 I had thought that it was supposed to run on the b
Marc Treib 2016/05/11 10:20:28 Acknowledged.
292 return;
293 }
294
295 is_fallback_ = false;
Marc Treib 2016/05/10 08:32:42 Initialize this in the initializer list above? I d
sfiera 2016/05/11 09:00:24 Done.
278 FetchPopularSites( 296 FetchPopularSites(
279 override_url.is_valid() ? override_url : GetPopularSitesURL(), 297 override_url.is_valid() ? override_url : GetPopularSitesURL(),
280 should_redownload_if_exists, false /* is_fallback */); 298 should_redownload_if_exists);
281 } 299 }
282 300
283 GURL PopularSites::GetPopularSitesURL() const { 301 GURL PopularSites::GetPopularSitesURL() const {
284 return GURL(base::StringPrintf(kPopularSitesURLFormat, 302 return GURL(base::StringPrintf(kPopularSitesURLFormat,
285 pending_country_.c_str(), 303 pending_country_.c_str(),
286 pending_version_.c_str())); 304 pending_version_.c_str()));
287 } 305 }
288 306
289 void PopularSites::FetchPopularSites(const GURL& url, 307 void PopularSites::FetchPopularSites(const GURL& url, bool force_download) {
Marc Treib 2016/05/10 08:32:42 Split this into two methods, since the force vs no
sfiera 2016/05/11 09:00:24 I've inlined it above and kept only the actual fet
290 bool force_download, 308 if (force_download) {
291 bool is_fallback) { 309 fetcher_ = URLFetcher::Create(url, URLFetcher::GET, this);
292 downloader_.reset(new FileDownloader( 310 fetcher_->SetRequestContext(download_context_);
293 url, local_path_, force_download, download_context_, 311 fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES |
294 base::Bind(&PopularSites::OnDownloadDone, base::Unretained(this), 312 net::LOAD_DO_NOT_SAVE_COOKIES);
295 is_fallback))); 313 fetcher_->SetAutomaticallyRetryOnNetworkChanges(1);
296 } 314 fetcher_->Start();
297 315 } else {
298 void PopularSites::OnDownloadDone(bool is_fallback, 316 base::PostTaskAndReplyWithResult(
299 FileDownloader::Result result) { 317 BrowserThread::GetBlockingPool()
300 downloader_.reset(); 318 ->GetTaskRunnerWithShutdownBehavior(
301 switch (result) { 319 base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN)
302 case FileDownloader::DOWNLOADED: 320 .get(),
Marc Treib 2016/05/10 08:32:43 IMO these four lines are now repeated often enough
sfiera 2016/05/11 09:00:24 Did one further.
303 prefs_->SetInt64(kPopularSitesLastDownloadPref, 321 FROM_HERE, base::Bind(&base::PathExists, local_path_),
304 base::Time::Now().ToInternalValue()); 322 base::Bind(&PopularSites::OnFileExistsCheckDone,
305 prefs_->SetString(kPopularSitesCountryPref, pending_country_); 323 weak_ptr_factory_.GetWeakPtr(), url));
306 prefs_->SetString(kPopularSitesVersionPref, pending_version_);
307 ParseSiteList(local_path_);
308 break;
309 case FileDownloader::EXISTS:
310 ParseSiteList(local_path_);
311 break;
312 case FileDownloader::FAILED:
313 if (!is_fallback) {
314 DLOG(WARNING) << "Download country site list failed";
315 pending_country_ = kPopularSitesDefaultCountryCode;
316 pending_version_ = kPopularSitesDefaultVersion;
317 // It is fine to force the download as Fallback is only triggered after
318 // a failed download.
319 FetchPopularSites(GetPopularSitesURL(), true /* force_download */,
320 true /* is_fallback */);
321 } else {
322 DLOG(WARNING) << "Download fallback site list failed";
323 callback_.Run(false);
324 }
325 break;
326 } 324 }
327 } 325 }
328 326
329 void PopularSites::ParseSiteList(const base::FilePath& path) { 327 void PopularSites::OnDownloadFailed() {
328 if (!is_fallback_) {
329 DLOG(WARNING) << "Download country site list failed";
330 is_fallback_ = true;
331 pending_country_ = kPopularSitesDefaultCountryCode;
332 pending_version_ = kPopularSitesDefaultVersion;
333 // It is fine to force the download as Fallback is only triggered after
334 // a failed download.
335 FetchPopularSites(GetPopularSitesURL(), true /* force_download */);
336 } else {
337 DLOG(WARNING) << "Download fallback site list failed";
338 callback_.Run(false);
339 }
340 }
341
342 void PopularSites::OnFileExistsCheckDone(const GURL& url, bool exists) {
343 if (exists) {
344 std::string json;
345 if (base::ReadFileToString(local_path_, &json)) {
Marc Treib 2016/05/10 08:32:43 This runs on the UI thread, right? That thread isn
sfiera 2016/05/10 08:44:51 I should have said up front: I have no real idea w
Marc Treib 2016/05/10 09:04:07 Rule of thumb: We're on the UI thread. :D DCHECK_C
sfiera 2016/05/11 09:00:24 Added it to the constructor. Should I add a commen
Marc Treib 2016/05/11 10:20:28 Adding a comment to the header is definitely appre
346 ParseSiteList(json);
347 } else {
348 // TODO(sfiera): remove and retry?
349 DLOG(WARNING) << "Failed reading file";
350 callback_.Run(false);
351 }
352 } else {
353 FetchPopularSites(url, true /* force_download */);
354 }
355 }
356
357 void PopularSites::OnURLFetchComplete(const net::URLFetcher* source) {
358 DCHECK_EQ(fetcher_.get(), source);
359 fetcher_.reset();
360
361 std::string sketchy_json;
362 if (!(source->GetStatus().is_success() &&
363 source->GetResponseCode() == net::HTTP_OK &&
364 source->GetResponseAsString(&sketchy_json))) {
365 OnDownloadFailed();
366 return;
367 }
368
369 safe_json::JsonSanitizer::Sanitize(
370 sketchy_json, base::Bind(&PopularSites::OnJsonSanitized,
371 weak_ptr_factory_.GetWeakPtr()),
372 base::Bind(&PopularSites::OnJsonSanitizationFailed,
373 weak_ptr_factory_.GetWeakPtr()));
374 }
375
376 void PopularSites::OnJsonSanitized(const std::string& valid_minified_json) {
330 base::PostTaskAndReplyWithResult( 377 base::PostTaskAndReplyWithResult(
331 BrowserThread::GetBlockingPool() 378 BrowserThread::GetBlockingPool()
332 ->GetTaskRunnerWithShutdownBehavior( 379 ->GetTaskRunnerWithShutdownBehavior(
333 base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN) 380 base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN)
334 .get(), 381 .get(),
335 FROM_HERE, base::Bind(&ReadAndParseJsonFile, path), 382 FROM_HERE,
383 base::Bind(&WriteStringToFileAtomic, valid_minified_json, local_path_),
384 base::Bind(&PopularSites::OnFileWriteDone, weak_ptr_factory_.GetWeakPtr(),
385 valid_minified_json));
386 }
387
388 void PopularSites::OnJsonSanitizationFailed(const std::string& error_message) {
389 DLOG(WARNING) << "JSON sanitization failed: " << error_message;
390 OnDownloadFailed();
391 }
392
393 void PopularSites::OnFileWriteDone(const std::string& json, bool success) {
394 if (success) {
395 OnHaveNewFile(json);
396 } else {
397 DLOG(WARNING) << "could not write file to "
Marc Treib 2016/05/10 08:32:43 nitty nit: Start with a capital letter
sfiera 2016/05/11 09:00:24 Done.
398 << local_path_.LossyDisplayName();
399 OnDownloadFailed();
400 }
401 }
402
403 void PopularSites::OnHaveNewFile(const std::string& json) {
404 prefs_->SetInt64(kPopularSitesLastDownloadPref,
405 base::Time::Now().ToInternalValue());
406 prefs_->SetString(kPopularSitesCountryPref, pending_country_);
407 prefs_->SetString(kPopularSitesVersionPref, pending_version_);
408 ParseSiteList(json);
409 }
410
411 void PopularSites::ParseSiteList(const std::string& json) {
412 base::PostTaskAndReplyWithResult(
413 BrowserThread::GetBlockingPool()
414 ->GetTaskRunnerWithShutdownBehavior(
415 base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN)
416 .get(),
417 FROM_HERE, base::Bind(&ParseJsonFile, json),
336 base::Bind(&PopularSites::OnJsonParsed, weak_ptr_factory_.GetWeakPtr())); 418 base::Bind(&PopularSites::OnJsonParsed, weak_ptr_factory_.GetWeakPtr()));
337 } 419 }
338 420
339 void PopularSites::OnJsonParsed(std::unique_ptr<std::vector<Site>> sites) { 421 void PopularSites::OnJsonParsed(std::unique_ptr<std::vector<Site>> sites) {
340 if (sites) 422 if (sites)
341 sites_.swap(*sites); 423 sites_.swap(*sites);
342 else 424 else
343 sites_.clear(); 425 sites_.clear();
344 callback_.Run(!!sites); 426 callback_.Run(!!sites);
345 } 427 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698