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

Side by Side Diff: components/ntp_snippets/ntp_snippets_service.cc

Issue 2227973002: Add request throttler to thumbnail fetching for articles on mobile NTP (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: One forgotten comment Created 4 years, 4 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 "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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698