Chromium Code Reviews| 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 <iterator> | 8 #include <iterator> |
| 9 #include <utility> | 9 #include <utility> |
| 10 | 10 |
| (...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 205 suggestions_service_(suggestions_service), | 205 suggestions_service_(suggestions_service), |
| 206 application_language_code_(application_language_code), | 206 application_language_code_(application_language_code), |
| 207 scheduler_(scheduler), | 207 scheduler_(scheduler), |
| 208 snippets_fetcher_(std::move(snippets_fetcher)), | 208 snippets_fetcher_(std::move(snippets_fetcher)), |
| 209 image_fetcher_(std::move(image_fetcher)), | 209 image_fetcher_(std::move(image_fetcher)), |
| 210 image_decoder_(std::move(image_decoder)), | 210 image_decoder_(std::move(image_decoder)), |
| 211 database_(std::move(database)), | 211 database_(std::move(database)), |
| 212 snippets_status_service_(std::move(status_service)), | 212 snippets_status_service_(std::move(status_service)), |
| 213 fetch_after_load_(false), | 213 fetch_after_load_(false), |
| 214 provided_category_( | 214 provided_category_( |
| 215 category_factory->FromKnownCategory(KnownCategories::ARTICLES)) { | 215 category_factory->FromKnownCategory(KnownCategories::ARTICLES)), |
| 216 thumbnail_requests_throttler_( | |
| 217 pref_service, | |
| 218 RequestThrottler::RequestType::CONTENT_SUGGESTION_THUMBNAIL) { | |
| 216 if (database_->IsErrorState()) { | 219 if (database_->IsErrorState()) { |
| 217 EnterState(State::ERROR_OCCURRED, CategoryStatus::LOADING_ERROR); | 220 EnterState(State::ERROR_OCCURRED, CategoryStatus::LOADING_ERROR); |
| 218 return; | 221 return; |
| 219 } | 222 } |
| 220 | 223 |
| 221 database_->SetErrorCallback(base::Bind(&NTPSnippetsService::OnDatabaseError, | 224 database_->SetErrorCallback(base::Bind(&NTPSnippetsService::OnDatabaseError, |
| 222 base::Unretained(this))); | 225 base::Unretained(this))); |
| 223 | 226 |
| 224 // We transition to other states while finalizing the initialization, when the | 227 // We transition to other states while finalizing the initialization, when the |
| 225 // database is done loading. | 228 // database is done loading. |
| 226 database_->LoadSnippets(base::Bind(&NTPSnippetsService::OnDatabaseLoaded, | 229 database_->LoadSnippets(base::Bind(&NTPSnippetsService::OnDatabaseLoaded, |
| 227 base::Unretained(this))); | 230 base::Unretained(this))); |
| 228 } | 231 } |
| 229 | 232 |
| 230 NTPSnippetsService::~NTPSnippetsService() { | 233 NTPSnippetsService::~NTPSnippetsService() { |
| 231 } | 234 } |
| 232 | 235 |
| 233 // static | 236 // static |
| 234 void NTPSnippetsService::RegisterProfilePrefs(PrefRegistrySimple* registry) { | 237 void NTPSnippetsService::RegisterProfilePrefs(PrefRegistrySimple* registry) { |
| 235 registry->RegisterListPref(prefs::kSnippetHosts); | 238 registry->RegisterListPref(prefs::kSnippetHosts); |
| 236 | 239 |
| 237 NTPSnippetsStatusService::RegisterProfilePrefs(registry); | 240 NTPSnippetsStatusService::RegisterProfilePrefs(registry); |
| 238 } | 241 } |
| 239 | 242 |
| 240 void NTPSnippetsService::FetchSnippets(bool force_request) { | 243 void NTPSnippetsService::FetchSnippets(bool interactive_request) { |
| 241 if (ready()) | 244 if (ready()) |
| 242 FetchSnippetsFromHosts(GetSuggestionsHosts(), force_request); | 245 FetchSnippetsFromHosts(GetSuggestionsHosts(), interactive_request); |
| 243 else | 246 else |
| 244 fetch_after_load_ = true; | 247 fetch_after_load_ = true; |
| 245 } | 248 } |
| 246 | 249 |
| 247 void NTPSnippetsService::FetchSnippetsFromHosts( | 250 void NTPSnippetsService::FetchSnippetsFromHosts( |
| 248 const std::set<std::string>& hosts, | 251 const std::set<std::string>& hosts, |
| 249 bool force_request) { | 252 bool interactive_request) { |
| 250 if (!ready()) | 253 if (!ready()) |
| 251 return; | 254 return; |
| 252 | 255 |
| 253 if (snippets_.empty()) | 256 if (snippets_.empty()) |
| 254 UpdateCategoryStatus(CategoryStatus::AVAILABLE_LOADING); | 257 UpdateCategoryStatus(CategoryStatus::AVAILABLE_LOADING); |
| 255 | 258 |
| 256 snippets_fetcher_->FetchSnippetsFromHosts(hosts, application_language_code_, | 259 snippets_fetcher_->FetchSnippetsFromHosts( |
| 257 kMaxSnippetCount, force_request); | 260 hosts, application_language_code_, kMaxSnippetCount, interactive_request); |
| 258 } | 261 } |
| 259 | 262 |
| 260 void NTPSnippetsService::RescheduleFetching() { | 263 void NTPSnippetsService::RescheduleFetching() { |
| 261 // The scheduler only exists on Android so far, it's null on other platforms. | 264 // The scheduler only exists on Android so far, it's null on other platforms. |
| 262 if (!scheduler_) | 265 if (!scheduler_) |
| 263 return; | 266 return; |
| 264 | 267 |
| 265 if (ready()) { | 268 if (ready()) { |
| 266 base::Time now = base::Time::Now(); | 269 base::Time now = base::Time::Now(); |
| 267 scheduler_->Schedule( | 270 scheduler_->Schedule( |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 310 snippets_.erase(it); | 313 snippets_.erase(it); |
| 311 } | 314 } |
| 312 | 315 |
| 313 void NTPSnippetsService::FetchSuggestionImage( | 316 void NTPSnippetsService::FetchSuggestionImage( |
| 314 const std::string& suggestion_id, | 317 const std::string& suggestion_id, |
| 315 const ImageFetchedCallback& callback) { | 318 const ImageFetchedCallback& callback) { |
| 316 std::string snippet_id = GetWithinCategoryIDFromUniqueID(suggestion_id); | 319 std::string snippet_id = GetWithinCategoryIDFromUniqueID(suggestion_id); |
| 317 database_->LoadImage( | 320 database_->LoadImage( |
| 318 snippet_id, | 321 snippet_id, |
| 319 base::Bind(&NTPSnippetsService::OnSnippetImageFetchedFromDatabase, | 322 base::Bind(&NTPSnippetsService::OnSnippetImageFetchedFromDatabase, |
| 320 base::Unretained(this), snippet_id, callback)); | 323 base::Unretained(this), callback, snippet_id)); |
| 321 } | 324 } |
| 322 | 325 |
| 323 void NTPSnippetsService::ClearCachedSuggestionsForDebugging(Category category) { | 326 void NTPSnippetsService::ClearCachedSuggestionsForDebugging(Category category) { |
| 324 DCHECK_EQ(category, provided_category_); | 327 DCHECK_EQ(category, provided_category_); |
| 325 if (!initialized()) | 328 if (!initialized()) |
| 326 return; | 329 return; |
| 327 | 330 |
| 328 if (snippets_.empty()) | 331 if (snippets_.empty()) |
| 329 return; | 332 return; |
| 330 | 333 |
| (...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 620 if (snippet->expiry_date() < next_expiry) | 623 if (snippet->expiry_date() < next_expiry) |
| 621 next_expiry = snippet->expiry_date(); | 624 next_expiry = snippet->expiry_date(); |
| 622 } | 625 } |
| 623 DCHECK_GT(next_expiry, expiry); | 626 DCHECK_GT(next_expiry, expiry); |
| 624 expiry_timer_.Start(FROM_HERE, next_expiry - expiry, | 627 expiry_timer_.Start(FROM_HERE, next_expiry - expiry, |
| 625 base::Bind(&NTPSnippetsService::ClearExpiredSnippets, | 628 base::Bind(&NTPSnippetsService::ClearExpiredSnippets, |
| 626 base::Unretained(this))); | 629 base::Unretained(this))); |
| 627 } | 630 } |
| 628 | 631 |
| 629 void NTPSnippetsService::OnSnippetImageFetchedFromDatabase( | 632 void NTPSnippetsService::OnSnippetImageFetchedFromDatabase( |
| 633 const ImageFetchedCallback& callback, | |
| 630 const std::string& snippet_id, | 634 const std::string& snippet_id, |
| 631 const ImageFetchedCallback& callback, | |
| 632 std::string data) { | 635 std::string data) { |
| 633 // |image_decoder_| is null in tests. | 636 // |image_decoder_| is null in tests. |
| 634 if (image_decoder_ && !data.empty()) { | 637 if (image_decoder_ && !data.empty()) { |
| 635 image_decoder_->DecodeImage( | 638 image_decoder_->DecodeImage( |
| 636 std::move(data), | 639 std::move(data), |
| 637 base::Bind(&NTPSnippetsService::OnSnippetImageDecoded, | 640 base::Bind(&NTPSnippetsService::OnSnippetImageDecodedFromDatabase, |
| 638 base::Unretained(this), snippet_id, callback)); | 641 base::Unretained(this), callback, snippet_id)); |
| 639 return; | 642 return; |
| 640 } | 643 } |
| 641 | 644 |
| 642 // Fetching from the DB failed; start a network fetch. | 645 // Fetching from the DB failed; start a network fetch. |
| 643 FetchSnippetImageFromNetwork(snippet_id, callback); | 646 FetchSnippetImageFromNetwork(snippet_id, callback); |
| 644 } | 647 } |
| 645 | 648 |
| 646 void NTPSnippetsService::OnSnippetImageDecoded( | 649 void NTPSnippetsService::OnSnippetImageDecodedFromDatabase( |
| 650 const ImageFetchedCallback& callback, | |
| 647 const std::string& snippet_id, | 651 const std::string& snippet_id, |
| 648 const ImageFetchedCallback& callback, | |
| 649 const gfx::Image& image) { | 652 const gfx::Image& image) { |
| 650 if (!image.IsEmpty()) { | 653 if (!image.IsEmpty()) { |
| 651 callback.Run(MakeUniqueID(provided_category_, snippet_id), image); | 654 callback.Run(MakeUniqueID(provided_category_, snippet_id), image); |
| 652 return; | 655 return; |
| 653 } | 656 } |
| 654 | 657 |
| 655 // If decoding the image failed, delete the DB entry. | 658 // If decoding the image failed, delete the DB entry. |
| 656 database_->DeleteImage(snippet_id); | 659 database_->DeleteImage(snippet_id); |
| 657 | 660 |
| 658 FetchSnippetImageFromNetwork(snippet_id, callback); | 661 FetchSnippetImageFromNetwork(snippet_id, callback); |
| 659 } | 662 } |
| 660 | 663 |
| 664 void NTPSnippetsService::OnSnippetImageDecodedFromNetwork( | |
|
Marc Treib
2016/08/10 11:38:15
nit: move this below FetchSnippetImageFromNetwork,
jkrcal
2016/08/10 11:57:03
Done.
| |
| 665 const ImageFetchedCallback& callback, | |
| 666 const std::string& snippet_id, | |
| 667 const gfx::Image& image) { | |
| 668 callback.Run(MakeUniqueID(provided_category_, snippet_id), image); | |
| 669 } | |
| 670 | |
| 661 void NTPSnippetsService::FetchSnippetImageFromNetwork( | 671 void NTPSnippetsService::FetchSnippetImageFromNetwork( |
| 662 const std::string& snippet_id, | 672 const std::string& snippet_id, |
| 663 const ImageFetchedCallback& callback) { | 673 const ImageFetchedCallback& callback) { |
| 664 auto it = | 674 auto it = |
| 665 std::find_if(snippets_.begin(), snippets_.end(), | 675 std::find_if(snippets_.begin(), snippets_.end(), |
| 666 [&snippet_id](const std::unique_ptr<NTPSnippet>& snippet) { | 676 [&snippet_id](const std::unique_ptr<NTPSnippet>& snippet) { |
| 667 return snippet->id() == snippet_id; | 677 return snippet->id() == snippet_id; |
| 668 }); | 678 }); |
| 669 if (it == snippets_.end()) { | 679 |
| 670 callback.Run(MakeUniqueID(provided_category_, snippet_id), gfx::Image()); | 680 if (it == snippets_.end() || |
| 681 !thumbnail_requests_throttler_.DemandQuotaForRequest( | |
| 682 /*interactive_request=*/true)) { | |
| 683 // Return an empty image. | |
| 684 base::ThreadTaskRunnerHandle::Get()->PostTask( | |
|
Marc Treib
2016/08/10 11:38:15
I think we can directly call the method here, sinc
jkrcal
2016/08/10 11:57:03
Done.
Why is it unsafe here when it is safe anywh
Marc Treib
2016/08/10 12:04:59
It should be safe below because it's the image_fet
jkrcal
2016/08/10 16:22:27
Thanks, makes sense!
| |
| 685 FROM_HERE, | |
| 686 base::Bind(&NTPSnippetsService::OnSnippetImageDecodedFromNetwork, | |
| 687 base::Unretained(this), callback, snippet_id, gfx::Image())); | |
| 671 return; | 688 return; |
| 672 } | 689 } |
| 673 | 690 |
| 674 const NTPSnippet& snippet = *it->get(); | 691 const NTPSnippet& snippet = *it->get(); |
| 692 | |
| 693 // The image fetcher calls OnImageDataFetched() with the raw data (this object | |
| 694 // is an ImageFetcherDelegate) and then also | |
| 695 // OnSnippetImageDecodedFromNetwork() after the raw data gets decoded. | |
| 675 image_fetcher_->StartOrQueueNetworkRequest( | 696 image_fetcher_->StartOrQueueNetworkRequest( |
| 676 snippet.id(), snippet.salient_image_url(), callback); | 697 snippet.id(), snippet.salient_image_url(), |
| 698 base::Bind(&NTPSnippetsService::OnSnippetImageDecodedFromNetwork, | |
| 699 base::Unretained(this), callback)); | |
|
Marc Treib
2016/08/10 11:38:15
misaligned
jkrcal
2016/08/10 11:57:03
Done.
| |
| 677 } | 700 } |
| 678 | 701 |
| 679 void NTPSnippetsService::EnterStateEnabled(bool fetch_snippets) { | 702 void NTPSnippetsService::EnterStateEnabled(bool fetch_snippets) { |
| 680 if (fetch_snippets) | 703 if (fetch_snippets) |
| 681 FetchSnippets(/*force_request=*/false); | 704 FetchSnippets(/*force_request=*/false); |
| 682 | 705 |
| 683 // FetchSnippets should set the status to |AVAILABLE_LOADING| if relevant, | 706 // FetchSnippets should set the status to |AVAILABLE_LOADING| if relevant, |
| 684 // otherwise we transition to |AVAILABLE| here. | 707 // otherwise we transition to |AVAILABLE| here. |
| 685 if (category_status_ != CategoryStatus::AVAILABLE_LOADING) | 708 if (category_status_ != CategoryStatus::AVAILABLE_LOADING) |
| 686 UpdateCategoryStatus(CategoryStatus::AVAILABLE); | 709 UpdateCategoryStatus(CategoryStatus::AVAILABLE); |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 813 void NTPSnippetsService::UpdateCategoryStatus(CategoryStatus status) { | 836 void NTPSnippetsService::UpdateCategoryStatus(CategoryStatus status) { |
| 814 if (status == category_status_) | 837 if (status == category_status_) |
| 815 return; | 838 return; |
| 816 | 839 |
| 817 category_status_ = status; | 840 category_status_ = status; |
| 818 observer()->OnCategoryStatusChanged(this, provided_category_, | 841 observer()->OnCategoryStatusChanged(this, provided_category_, |
| 819 category_status_); | 842 category_status_); |
| 820 } | 843 } |
| 821 | 844 |
| 822 } // namespace ntp_snippets | 845 } // namespace ntp_snippets |
| OLD | NEW |