| 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_tiles/popular_sites.h" | 5 #include "components/ntp_tiles/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" |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 120 : title(title), | 120 : title(title), |
| 121 url(url), | 121 url(url), |
| 122 favicon_url(favicon_url), | 122 favicon_url(favicon_url), |
| 123 large_icon_url(large_icon_url), | 123 large_icon_url(large_icon_url), |
| 124 thumbnail_url(thumbnail_url) {} | 124 thumbnail_url(thumbnail_url) {} |
| 125 | 125 |
| 126 PopularSites::Site::Site(const Site& other) = default; | 126 PopularSites::Site::Site(const Site& other) = default; |
| 127 | 127 |
| 128 PopularSites::Site::~Site() {} | 128 PopularSites::Site::~Site() {} |
| 129 | 129 |
| 130 PopularSites::PopularSites( | 130 PopularSitesImpl::PopularSitesImpl( |
| 131 const scoped_refptr<base::SequencedWorkerPool>& blocking_pool, | 131 const scoped_refptr<base::SequencedWorkerPool>& blocking_pool, |
| 132 PrefService* prefs, | 132 PrefService* prefs, |
| 133 const TemplateURLService* template_url_service, | 133 const TemplateURLService* template_url_service, |
| 134 VariationsService* variations_service, | 134 VariationsService* variations_service, |
| 135 net::URLRequestContextGetter* download_context, | 135 net::URLRequestContextGetter* download_context, |
| 136 const base::FilePath& directory, | 136 const base::FilePath& directory, |
| 137 ParseJSONCallback parse_json) | 137 ParseJSONCallback parse_json) |
| 138 : blocking_runner_(blocking_pool->GetTaskRunnerWithShutdownBehavior( | 138 : blocking_runner_(blocking_pool->GetTaskRunnerWithShutdownBehavior( |
| 139 base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN)), | 139 base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN)), |
| 140 prefs_(prefs), | 140 prefs_(prefs), |
| 141 template_url_service_(template_url_service), | 141 template_url_service_(template_url_service), |
| 142 variations_(variations_service), | 142 variations_(variations_service), |
| 143 download_context_(download_context), | 143 download_context_(download_context), |
| 144 local_path_(directory.empty() | 144 local_path_(directory.empty() |
| 145 ? base::FilePath() | 145 ? base::FilePath() |
| 146 : directory.AppendASCII(kPopularSitesLocalFilename)), | 146 : directory.AppendASCII(kPopularSitesLocalFilename)), |
| 147 parse_json_(std::move(parse_json)), | 147 parse_json_(std::move(parse_json)), |
| 148 is_fallback_(false), | 148 is_fallback_(false), |
| 149 weak_ptr_factory_(this) {} | 149 weak_ptr_factory_(this) {} |
| 150 | 150 |
| 151 PopularSites::~PopularSites() {} | 151 PopularSitesImpl::~PopularSitesImpl() {} |
| 152 | 152 |
| 153 void PopularSites::StartFetch(bool force_download, | 153 void PopularSitesImpl::StartFetch(bool force_download, |
| 154 const FinishedCallback& callback) { | 154 const FinishedCallback& callback) { |
| 155 DCHECK(!callback_); | 155 DCHECK(!callback_); |
| 156 callback_ = callback; | 156 callback_ = callback; |
| 157 | 157 |
| 158 const base::Time last_download_time = base::Time::FromInternalValue( | 158 const base::Time last_download_time = base::Time::FromInternalValue( |
| 159 prefs_->GetInt64(kPopularSitesLastDownloadPref)); | 159 prefs_->GetInt64(kPopularSitesLastDownloadPref)); |
| 160 const base::TimeDelta time_since_last_download = | 160 const base::TimeDelta time_since_last_download = |
| 161 base::Time::Now() - last_download_time; | 161 base::Time::Now() - last_download_time; |
| 162 const base::TimeDelta redownload_interval = | 162 const base::TimeDelta redownload_interval = |
| 163 base::TimeDelta::FromHours(kPopularSitesRedownloadIntervalHours); | 163 base::TimeDelta::FromHours(kPopularSitesRedownloadIntervalHours); |
| 164 const bool download_time_is_future = base::Time::Now() < last_download_time; | 164 const bool download_time_is_future = base::Time::Now() < last_download_time; |
| 165 | 165 |
| 166 pending_url_ = GetURLToUse(); | 166 pending_url_ = GetURLToFetch(); |
| 167 const bool url_changed = | 167 const bool url_changed = |
| 168 pending_url_.spec() != prefs_->GetString(kPopularSitesURLPref); | 168 pending_url_.spec() != prefs_->GetString(kPopularSitesURLPref); |
| 169 | 169 |
| 170 // No valid path to save to. Immediately post failure. | 170 // No valid path to save to. Immediately post failure. |
| 171 if (local_path_.empty()) { | 171 if (local_path_.empty()) { |
| 172 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, | 172 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, |
| 173 base::Bind(callback_, false)); | 173 base::Bind(callback_, false)); |
| 174 return; | 174 return; |
| 175 } | 175 } |
| 176 | 176 |
| 177 // Download forced, or we need to download a new file. | 177 // Download forced, or we need to download a new file. |
| 178 if (force_download || download_time_is_future || | 178 if (force_download || download_time_is_future || |
| 179 (time_since_last_download > redownload_interval) || url_changed) { | 179 (time_since_last_download > redownload_interval) || url_changed) { |
| 180 FetchPopularSites(); | 180 FetchPopularSites(); |
| 181 return; | 181 return; |
| 182 } | 182 } |
| 183 | 183 |
| 184 std::unique_ptr<std::string> file_data(new std::string); | 184 std::unique_ptr<std::string> file_data(new std::string); |
| 185 std::string* file_data_ptr = file_data.get(); | 185 std::string* file_data_ptr = file_data.get(); |
| 186 base::PostTaskAndReplyWithResult( | 186 base::PostTaskAndReplyWithResult( |
| 187 blocking_runner_.get(), FROM_HERE, | 187 blocking_runner_.get(), FROM_HERE, |
| 188 base::Bind(&base::ReadFileToString, local_path_, file_data_ptr), | 188 base::Bind(&base::ReadFileToString, local_path_, file_data_ptr), |
| 189 base::Bind(&PopularSites::OnReadFileDone, weak_ptr_factory_.GetWeakPtr(), | 189 base::Bind(&PopularSitesImpl::OnReadFileDone, |
| 190 weak_ptr_factory_.GetWeakPtr(), |
| 190 base::Passed(std::move(file_data)))); | 191 base::Passed(std::move(file_data)))); |
| 191 } | 192 } |
| 192 | 193 |
| 193 GURL PopularSites::LastURL() const { | 194 const PopularSites::SitesVector& PopularSitesImpl::sites() const { |
| 195 return sites_; |
| 196 } |
| 197 |
| 198 GURL PopularSitesImpl::GetLastURLFetched() const { |
| 194 return GURL(prefs_->GetString(kPopularSitesURLPref)); | 199 return GURL(prefs_->GetString(kPopularSitesURLPref)); |
| 195 } | 200 } |
| 196 | 201 |
| 197 GURL PopularSites::GetURLToUse() { | 202 const base::FilePath& PopularSitesImpl::local_path() const { |
| 198 const std::string country = GetCountryToUse(); | 203 return local_path_; |
| 199 const std::string version = GetVersionToUse(); | 204 } |
| 205 |
| 206 GURL PopularSitesImpl::GetURLToFetch() { |
| 207 const std::string country = GetCountryToFetch(); |
| 208 const std::string version = GetVersionToFetch(); |
| 200 | 209 |
| 201 const GURL override_url = | 210 const GURL override_url = |
| 202 GURL(prefs_->GetString(ntp_tiles::prefs::kPopularSitesOverrideURL)); | 211 GURL(prefs_->GetString(ntp_tiles::prefs::kPopularSitesOverrideURL)); |
| 203 return override_url.is_valid() ? override_url | 212 return override_url.is_valid() ? override_url |
| 204 : GetPopularSitesURL(country, version); | 213 : GetPopularSitesURL(country, version); |
| 205 } | 214 } |
| 206 | 215 |
| 207 // Determine the country code to use. In order of precedence: | 216 // Determine the country code to use. In order of precedence: |
| 208 // - The explicit "override country" pref set by the user. | 217 // - The explicit "override country" pref set by the user. |
| 209 // - The country code from the field trial config (variation parameter). | 218 // - The country code from the field trial config (variation parameter). |
| 210 // - The Google country code if Google is the default search engine (and the | 219 // - The Google country code if Google is the default search engine (and the |
| 211 // "--enable-ntp-search-engine-country-detection" switch is present). | 220 // "--enable-ntp-search-engine-country-detection" switch is present). |
| 212 // - The country provided by the VariationsService. | 221 // - The country provided by the VariationsService. |
| 213 // - A default fallback. | 222 // - A default fallback. |
| 214 std::string PopularSites::GetCountryToUse() { | 223 std::string PopularSitesImpl::GetCountryToFetch() { |
| 215 std::string country_code = | 224 std::string country_code = |
| 216 prefs_->GetString(ntp_tiles::prefs::kPopularSitesOverrideCountry); | 225 prefs_->GetString(ntp_tiles::prefs::kPopularSitesOverrideCountry); |
| 217 | 226 |
| 218 if (country_code.empty()) | 227 if (country_code.empty()) |
| 219 country_code = GetVariationCountry(); | 228 country_code = GetVariationCountry(); |
| 220 | 229 |
| 221 if (country_code.empty()) | 230 if (country_code.empty()) |
| 222 country_code = GetDefaultSearchEngineCountryCode(template_url_service_); | 231 country_code = GetDefaultSearchEngineCountryCode(template_url_service_); |
| 223 | 232 |
| 224 if (country_code.empty() && variations_) | 233 if (country_code.empty() && variations_) |
| 225 country_code = variations_->GetStoredPermanentCountry(); | 234 country_code = variations_->GetStoredPermanentCountry(); |
| 226 | 235 |
| 227 #if defined(OS_IOS) | 236 #if defined(OS_IOS) |
| 228 if (country_code.empty()) | 237 if (country_code.empty()) |
| 229 country_code = GetDeviceCountryCode(); | 238 country_code = GetDeviceCountryCode(); |
| 230 #endif | 239 #endif |
| 231 | 240 |
| 232 if (country_code.empty()) | 241 if (country_code.empty()) |
| 233 country_code = kPopularSitesDefaultCountryCode; | 242 country_code = kPopularSitesDefaultCountryCode; |
| 234 | 243 |
| 235 return base::ToUpperASCII(country_code); | 244 return base::ToUpperASCII(country_code); |
| 236 } | 245 } |
| 237 | 246 |
| 238 // Determine the version to use. In order of precedence: | 247 // Determine the version to use. In order of precedence: |
| 239 // - The explicit "override version" pref set by the user. | 248 // - The explicit "override version" pref set by the user. |
| 240 // - The version from the field trial config (variation parameter). | 249 // - The version from the field trial config (variation parameter). |
| 241 // - A default fallback. | 250 // - A default fallback. |
| 242 std::string PopularSites::GetVersionToUse() { | 251 std::string PopularSitesImpl::GetVersionToFetch() { |
| 243 std::string version = | 252 std::string version = |
| 244 prefs_->GetString(ntp_tiles::prefs::kPopularSitesOverrideVersion); | 253 prefs_->GetString(ntp_tiles::prefs::kPopularSitesOverrideVersion); |
| 245 | 254 |
| 246 if (version.empty()) | 255 if (version.empty()) |
| 247 version = GetVariationVersion(); | 256 version = GetVariationVersion(); |
| 248 | 257 |
| 249 if (version.empty()) | 258 if (version.empty()) |
| 250 version = kPopularSitesDefaultVersion; | 259 version = kPopularSitesDefaultVersion; |
| 251 | 260 |
| 252 return version; | 261 return version; |
| 253 } | 262 } |
| 254 | 263 |
| 255 // static | 264 // static |
| 256 void PopularSites::RegisterProfilePrefs( | 265 void PopularSitesImpl::RegisterProfilePrefs( |
| 257 user_prefs::PrefRegistrySyncable* user_prefs) { | 266 user_prefs::PrefRegistrySyncable* user_prefs) { |
| 258 user_prefs->RegisterStringPref(ntp_tiles::prefs::kPopularSitesOverrideURL, | 267 user_prefs->RegisterStringPref(ntp_tiles::prefs::kPopularSitesOverrideURL, |
| 259 std::string()); | 268 std::string()); |
| 260 user_prefs->RegisterStringPref(ntp_tiles::prefs::kPopularSitesOverrideCountry, | 269 user_prefs->RegisterStringPref(ntp_tiles::prefs::kPopularSitesOverrideCountry, |
| 261 std::string()); | 270 std::string()); |
| 262 user_prefs->RegisterStringPref(ntp_tiles::prefs::kPopularSitesOverrideVersion, | 271 user_prefs->RegisterStringPref(ntp_tiles::prefs::kPopularSitesOverrideVersion, |
| 263 std::string()); | 272 std::string()); |
| 264 | 273 |
| 265 user_prefs->RegisterInt64Pref(kPopularSitesLastDownloadPref, 0); | 274 user_prefs->RegisterInt64Pref(kPopularSitesLastDownloadPref, 0); |
| 266 user_prefs->RegisterStringPref(kPopularSitesURLPref, std::string()); | 275 user_prefs->RegisterStringPref(kPopularSitesURLPref, std::string()); |
| 267 } | 276 } |
| 268 | 277 |
| 269 void PopularSites::OnReadFileDone(std::unique_ptr<std::string> data, | 278 void PopularSitesImpl::OnReadFileDone(std::unique_ptr<std::string> data, |
| 270 bool success) { | 279 bool success) { |
| 271 if (success) { | 280 if (success) { |
| 272 auto json = base::JSONReader::Read(*data, base::JSON_ALLOW_TRAILING_COMMAS); | 281 auto json = base::JSONReader::Read(*data, base::JSON_ALLOW_TRAILING_COMMAS); |
| 273 if (json) { | 282 if (json) { |
| 274 ParseSiteList(std::move(json)); | 283 ParseSiteList(std::move(json)); |
| 275 } else { | 284 } else { |
| 276 OnJsonParseFailed("previously-fetched JSON was no longer parseable"); | 285 OnJsonParseFailed("previously-fetched JSON was no longer parseable"); |
| 277 } | 286 } |
| 278 } else { | 287 } else { |
| 279 // File didn't exist, or couldn't be read for some other reason. | 288 // File didn't exist, or couldn't be read for some other reason. |
| 280 FetchPopularSites(); | 289 FetchPopularSites(); |
| 281 } | 290 } |
| 282 } | 291 } |
| 283 | 292 |
| 284 void PopularSites::FetchPopularSites() { | 293 void PopularSitesImpl::FetchPopularSites() { |
| 285 fetcher_ = URLFetcher::Create(pending_url_, URLFetcher::GET, this); | 294 fetcher_ = URLFetcher::Create(pending_url_, URLFetcher::GET, this); |
| 286 data_use_measurement::DataUseUserData::AttachToFetcher( | 295 data_use_measurement::DataUseUserData::AttachToFetcher( |
| 287 fetcher_.get(), data_use_measurement::DataUseUserData::NTP_TILES); | 296 fetcher_.get(), data_use_measurement::DataUseUserData::NTP_TILES); |
| 288 fetcher_->SetRequestContext(download_context_); | 297 fetcher_->SetRequestContext(download_context_); |
| 289 fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | | 298 fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | |
| 290 net::LOAD_DO_NOT_SAVE_COOKIES); | 299 net::LOAD_DO_NOT_SAVE_COOKIES); |
| 291 fetcher_->SetAutomaticallyRetryOnNetworkChanges(1); | 300 fetcher_->SetAutomaticallyRetryOnNetworkChanges(1); |
| 292 fetcher_->Start(); | 301 fetcher_->Start(); |
| 293 } | 302 } |
| 294 | 303 |
| 295 void PopularSites::OnURLFetchComplete(const net::URLFetcher* source) { | 304 void PopularSitesImpl::OnURLFetchComplete(const net::URLFetcher* source) { |
| 296 DCHECK_EQ(fetcher_.get(), source); | 305 DCHECK_EQ(fetcher_.get(), source); |
| 297 std::unique_ptr<net::URLFetcher> free_fetcher = std::move(fetcher_); | 306 std::unique_ptr<net::URLFetcher> free_fetcher = std::move(fetcher_); |
| 298 | 307 |
| 299 std::string json_string; | 308 std::string json_string; |
| 300 if (!(source->GetStatus().is_success() && | 309 if (!(source->GetStatus().is_success() && |
| 301 source->GetResponseCode() == net::HTTP_OK && | 310 source->GetResponseCode() == net::HTTP_OK && |
| 302 source->GetResponseAsString(&json_string))) { | 311 source->GetResponseAsString(&json_string))) { |
| 303 OnDownloadFailed(); | 312 OnDownloadFailed(); |
| 304 return; | 313 return; |
| 305 } | 314 } |
| 306 | 315 |
| 307 parse_json_.Run( | 316 parse_json_.Run(json_string, base::Bind(&PopularSitesImpl::OnJsonParsed, |
| 308 json_string, | 317 weak_ptr_factory_.GetWeakPtr()), |
| 309 base::Bind(&PopularSites::OnJsonParsed, weak_ptr_factory_.GetWeakPtr()), | 318 base::Bind(&PopularSitesImpl::OnJsonParseFailed, |
| 310 base::Bind(&PopularSites::OnJsonParseFailed, | 319 weak_ptr_factory_.GetWeakPtr())); |
| 311 weak_ptr_factory_.GetWeakPtr())); | |
| 312 } | 320 } |
| 313 | 321 |
| 314 void PopularSites::OnJsonParsed(std::unique_ptr<base::Value> json) { | 322 void PopularSitesImpl::OnJsonParsed(std::unique_ptr<base::Value> json) { |
| 315 const base::Value* json_ptr = json.get(); | 323 const base::Value* json_ptr = json.get(); |
| 316 base::PostTaskAndReplyWithResult( | 324 base::PostTaskAndReplyWithResult( |
| 317 blocking_runner_.get(), FROM_HERE, | 325 blocking_runner_.get(), FROM_HERE, |
| 318 base::Bind(&WriteJsonToFile, local_path_, json_ptr), | 326 base::Bind(&WriteJsonToFile, local_path_, json_ptr), |
| 319 base::Bind(&PopularSites::OnFileWriteDone, weak_ptr_factory_.GetWeakPtr(), | 327 base::Bind(&PopularSitesImpl::OnFileWriteDone, |
| 328 weak_ptr_factory_.GetWeakPtr(), |
| 320 base::Passed(std::move(json)))); | 329 base::Passed(std::move(json)))); |
| 321 } | 330 } |
| 322 | 331 |
| 323 void PopularSites::OnJsonParseFailed(const std::string& error_message) { | 332 void PopularSitesImpl::OnJsonParseFailed(const std::string& error_message) { |
| 324 DLOG(WARNING) << "JSON parsing failed: " << error_message; | 333 DLOG(WARNING) << "JSON parsing failed: " << error_message; |
| 325 OnDownloadFailed(); | 334 OnDownloadFailed(); |
| 326 } | 335 } |
| 327 | 336 |
| 328 void PopularSites::OnFileWriteDone(std::unique_ptr<base::Value> json, | 337 void PopularSitesImpl::OnFileWriteDone(std::unique_ptr<base::Value> json, |
| 329 bool success) { | 338 bool success) { |
| 330 if (success) { | 339 if (success) { |
| 331 prefs_->SetInt64(kPopularSitesLastDownloadPref, | 340 prefs_->SetInt64(kPopularSitesLastDownloadPref, |
| 332 base::Time::Now().ToInternalValue()); | 341 base::Time::Now().ToInternalValue()); |
| 333 prefs_->SetString(kPopularSitesURLPref, pending_url_.spec()); | 342 prefs_->SetString(kPopularSitesURLPref, pending_url_.spec()); |
| 334 ParseSiteList(std::move(json)); | 343 ParseSiteList(std::move(json)); |
| 335 } else { | 344 } else { |
| 336 DLOG(WARNING) << "Could not write file to " | 345 DLOG(WARNING) << "Could not write file to " |
| 337 << local_path_.LossyDisplayName(); | 346 << local_path_.LossyDisplayName(); |
| 338 OnDownloadFailed(); | 347 OnDownloadFailed(); |
| 339 } | 348 } |
| 340 } | 349 } |
| 341 | 350 |
| 342 void PopularSites::ParseSiteList(std::unique_ptr<base::Value> json) { | 351 void PopularSitesImpl::ParseSiteList(std::unique_ptr<base::Value> json) { |
| 343 base::ListValue* list = nullptr; | 352 base::ListValue* list = nullptr; |
| 344 if (!json || !json->GetAsList(&list)) { | 353 if (!json || !json->GetAsList(&list)) { |
| 345 DLOG(WARNING) << "JSON is not a list"; | 354 DLOG(WARNING) << "JSON is not a list"; |
| 346 sites_.clear(); | 355 sites_.clear(); |
| 347 callback_.Run(false); | 356 callback_.Run(false); |
| 348 return; | 357 return; |
| 349 } | 358 } |
| 350 | 359 |
| 351 std::vector<PopularSites::Site> sites; | 360 SitesVector sites; |
| 352 for (size_t i = 0; i < list->GetSize(); i++) { | 361 for (size_t i = 0; i < list->GetSize(); i++) { |
| 353 base::DictionaryValue* item; | 362 base::DictionaryValue* item; |
| 354 if (!list->GetDictionary(i, &item)) | 363 if (!list->GetDictionary(i, &item)) |
| 355 continue; | 364 continue; |
| 356 base::string16 title; | 365 base::string16 title; |
| 357 std::string url; | 366 std::string url; |
| 358 if (!item->GetString("title", &title) || !item->GetString("url", &url)) | 367 if (!item->GetString("title", &title) || !item->GetString("url", &url)) |
| 359 continue; | 368 continue; |
| 360 std::string favicon_url; | 369 std::string favicon_url; |
| 361 item->GetString("favicon_url", &favicon_url); | 370 item->GetString("favicon_url", &favicon_url); |
| 362 std::string thumbnail_url; | 371 std::string thumbnail_url; |
| 363 item->GetString("thumbnail_url", &thumbnail_url); | 372 item->GetString("thumbnail_url", &thumbnail_url); |
| 364 std::string large_icon_url; | 373 std::string large_icon_url; |
| 365 item->GetString("large_icon_url", &large_icon_url); | 374 item->GetString("large_icon_url", &large_icon_url); |
| 366 | 375 |
| 367 sites.push_back(PopularSites::Site(title, GURL(url), GURL(favicon_url), | 376 sites.push_back(PopularSitesImpl::Site(title, GURL(url), GURL(favicon_url), |
| 368 GURL(large_icon_url), | 377 GURL(large_icon_url), |
| 369 GURL(thumbnail_url))); | 378 GURL(thumbnail_url))); |
| 370 } | 379 } |
| 371 | 380 |
| 372 sites_.swap(sites); | 381 sites_.swap(sites); |
| 373 callback_.Run(true); | 382 callback_.Run(true); |
| 374 } | 383 } |
| 375 | 384 |
| 376 void PopularSites::OnDownloadFailed() { | 385 void PopularSitesImpl::OnDownloadFailed() { |
| 377 if (!is_fallback_) { | 386 if (!is_fallback_) { |
| 378 DLOG(WARNING) << "Download country site list failed"; | 387 DLOG(WARNING) << "Download country site list failed"; |
| 379 is_fallback_ = true; | 388 is_fallback_ = true; |
| 380 pending_url_ = GetPopularSitesURL(kPopularSitesDefaultCountryCode, | 389 pending_url_ = GetPopularSitesURL(kPopularSitesDefaultCountryCode, |
| 381 kPopularSitesDefaultVersion); | 390 kPopularSitesDefaultVersion); |
| 382 FetchPopularSites(); | 391 FetchPopularSites(); |
| 383 } else { | 392 } else { |
| 384 DLOG(WARNING) << "Download fallback site list failed"; | 393 DLOG(WARNING) << "Download fallback site list failed"; |
| 385 callback_.Run(false); | 394 callback_.Run(false); |
| 386 } | 395 } |
| 387 } | 396 } |
| 388 | 397 |
| 389 } // namespace ntp_tiles | 398 } // namespace ntp_tiles |
| OLD | NEW |