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 290 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 621 if (snippet->expiry_date() < next_expiry) | 624 if (snippet->expiry_date() < next_expiry) |
| 622 next_expiry = snippet->expiry_date(); | 625 next_expiry = snippet->expiry_date(); |
| 623 } | 626 } |
| 624 DCHECK_GT(next_expiry, expiry); | 627 DCHECK_GT(next_expiry, expiry); |
| 625 expiry_timer_.Start(FROM_HERE, next_expiry - expiry, | 628 expiry_timer_.Start(FROM_HERE, next_expiry - expiry, |
| 626 base::Bind(&NTPSnippetsService::ClearExpiredSnippets, | 629 base::Bind(&NTPSnippetsService::ClearExpiredSnippets, |
| 627 base::Unretained(this))); | 630 base::Unretained(this))); |
| 628 } | 631 } |
| 629 | 632 |
| 630 void NTPSnippetsService::OnSnippetImageFetchedFromDatabase( | 633 void NTPSnippetsService::OnSnippetImageFetchedFromDatabase( |
| 634 const ImageFetchedCallback& callback, | |
| 631 const std::string& snippet_id, | 635 const std::string& snippet_id, |
| 632 const ImageFetchedCallback& callback, | |
| 633 std::string data) { | 636 std::string data) { |
| 634 // |image_decoder_| is null in tests. | 637 // |image_decoder_| is null in tests. |
| 635 if (image_decoder_ && !data.empty()) { | 638 if (image_decoder_ && !data.empty()) { |
| 636 image_decoder_->DecodeImage( | 639 image_decoder_->DecodeImage( |
| 637 std::move(data), | 640 std::move(data), |
| 638 base::Bind(&NTPSnippetsService::OnSnippetImageDecoded, | 641 base::Bind(&NTPSnippetsService::OnSnippetImageDecodedFromDatabase, |
| 639 base::Unretained(this), snippet_id, callback)); | 642 base::Unretained(this), callback, snippet_id)); |
| 640 return; | 643 return; |
| 641 } | 644 } |
| 642 | 645 |
| 643 // Fetching from the DB failed; start a network fetch. | 646 // Fetching from the DB failed; start a network fetch. |
| 644 FetchSnippetImageFromNetwork(snippet_id, callback); | 647 FetchSnippetImageFromNetwork(snippet_id, callback); |
| 645 } | 648 } |
| 646 | 649 |
| 647 void NTPSnippetsService::OnSnippetImageDecoded( | 650 void NTPSnippetsService::OnSnippetImageDecodedFromDatabase( |
| 651 const ImageFetchedCallback& callback, | |
| 648 const std::string& snippet_id, | 652 const std::string& snippet_id, |
| 649 const ImageFetchedCallback& callback, | |
| 650 const gfx::Image& image) { | 653 const gfx::Image& image) { |
| 651 if (!image.IsEmpty()) { | 654 if (!image.IsEmpty()) { |
| 652 callback.Run(MakeUniqueID(provided_category_, snippet_id), image); | 655 callback.Run(MakeUniqueID(provided_category_, snippet_id), image); |
| 653 return; | 656 return; |
| 654 } | 657 } |
| 655 | 658 |
| 656 // If decoding the image failed, delete the DB entry. | 659 // If decoding the image failed, delete the DB entry. |
| 657 database_->DeleteImage(snippet_id); | 660 database_->DeleteImage(snippet_id); |
| 658 | 661 |
| 659 FetchSnippetImageFromNetwork(snippet_id, callback); | 662 FetchSnippetImageFromNetwork(snippet_id, callback); |
| 660 } | 663 } |
| 661 | 664 |
| 662 void NTPSnippetsService::FetchSnippetImageFromNetwork( | 665 void NTPSnippetsService::FetchSnippetImageFromNetwork( |
| 663 const std::string& snippet_id, | 666 const std::string& snippet_id, |
| 664 const ImageFetchedCallback& callback) { | 667 const ImageFetchedCallback& callback) { |
| 665 auto it = | 668 auto it = |
| 666 std::find_if(snippets_.begin(), snippets_.end(), | 669 std::find_if(snippets_.begin(), snippets_.end(), |
| 667 [&snippet_id](const std::unique_ptr<NTPSnippet>& snippet) { | 670 [&snippet_id](const std::unique_ptr<NTPSnippet>& snippet) { |
| 668 return snippet->id() == snippet_id; | 671 return snippet->id() == snippet_id; |
| 669 }); | 672 }); |
| 670 if (it == snippets_.end()) { | 673 |
| 671 callback.Run(MakeUniqueID(provided_category_, snippet_id), gfx::Image()); | 674 if (it == snippets_.end() || |
| 675 !thumbnail_requests_throttler_.DemandQuotaForRequest( | |
| 676 /*interactive_request=*/true)) { | |
| 677 // Return an empty image. Directly, this is never synchronous with the | |
| 678 // original FetchSuggestionImage() call - an asynchronous database query has | |
| 679 // happened in the meantime. | |
|
tschumann
2016/08/16 14:56:55
i guess we want to record such events somewhere, h
jkrcal
2016/12/06 08:30:25
This event is recorded in the request throttler. D
| |
| 680 OnSnippetImageDecodedFromNetwork(callback, snippet_id, gfx::Image()); | |
| 672 return; | 681 return; |
| 673 } | 682 } |
| 674 | 683 |
| 675 const NTPSnippet& snippet = *it->get(); | 684 const NTPSnippet& snippet = *it->get(); |
| 685 | |
| 686 // The image fetcher calls OnImageDataFetched() with the raw data (this object | |
|
tschumann
2016/08/16 14:56:55
probably outside of this CL but I find comments li
jkrcal
2016/12/06 08:30:25
Ok, let's leave it up to a follow-up CL.
| |
| 687 // is an ImageFetcherDelegate) and then also | |
| 688 // OnSnippetImageDecodedFromNetwork() after the raw data gets decoded. | |
| 676 image_fetcher_->StartOrQueueNetworkRequest( | 689 image_fetcher_->StartOrQueueNetworkRequest( |
| 677 snippet.id(), snippet.salient_image_url(), callback); | 690 snippet.id(), snippet.salient_image_url(), |
| 691 base::Bind(&NTPSnippetsService::OnSnippetImageDecodedFromNetwork, | |
| 692 base::Unretained(this), callback)); | |
| 693 } | |
| 694 | |
| 695 void NTPSnippetsService::OnSnippetImageDecodedFromNetwork( | |
| 696 const ImageFetchedCallback& callback, | |
| 697 const std::string& snippet_id, | |
| 698 const gfx::Image& image) { | |
| 699 callback.Run(MakeUniqueID(provided_category_, snippet_id), image); | |
| 678 } | 700 } |
| 679 | 701 |
| 680 void NTPSnippetsService::EnterStateEnabled(bool fetch_snippets) { | 702 void NTPSnippetsService::EnterStateEnabled(bool fetch_snippets) { |
| 681 if (fetch_snippets) | 703 if (fetch_snippets) |
| 682 FetchSnippets(/*force_request=*/false); | 704 FetchSnippets(/*force_request=*/false); |
| 683 | 705 |
| 684 // FetchSnippets should set the status to |AVAILABLE_LOADING| if relevant, | 706 // FetchSnippets should set the status to |AVAILABLE_LOADING| if relevant, |
| 685 // otherwise we transition to |AVAILABLE| here. | 707 // otherwise we transition to |AVAILABLE| here. |
| 686 if (category_status_ != CategoryStatus::AVAILABLE_LOADING) | 708 if (category_status_ != CategoryStatus::AVAILABLE_LOADING) |
| 687 UpdateCategoryStatus(CategoryStatus::AVAILABLE); | 709 UpdateCategoryStatus(CategoryStatus::AVAILABLE); |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 814 void NTPSnippetsService::UpdateCategoryStatus(CategoryStatus status) { | 836 void NTPSnippetsService::UpdateCategoryStatus(CategoryStatus status) { |
| 815 if (status == category_status_) | 837 if (status == category_status_) |
| 816 return; | 838 return; |
| 817 | 839 |
| 818 category_status_ = status; | 840 category_status_ = status; |
| 819 observer()->OnCategoryStatusChanged(this, provided_category_, | 841 observer()->OnCategoryStatusChanged(this, provided_category_, |
| 820 category_status_); | 842 category_status_); |
| 821 } | 843 } |
| 822 | 844 |
| 823 } // namespace ntp_snippets | 845 } // namespace ntp_snippets |
| OLD | NEW |