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 |