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

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: Tim's comments #2 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 289 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
661 void NTPSnippetsService::FetchSnippetImageFromNetwork( 664 void NTPSnippetsService::FetchSnippetImageFromNetwork(
662 const std::string& snippet_id, 665 const std::string& snippet_id,
663 const ImageFetchedCallback& callback) { 666 const ImageFetchedCallback& callback) {
664 auto it = 667 auto it =
665 std::find_if(snippets_.begin(), snippets_.end(), 668 std::find_if(snippets_.begin(), snippets_.end(),
666 [&snippet_id](const std::unique_ptr<NTPSnippet>& snippet) { 669 [&snippet_id](const std::unique_ptr<NTPSnippet>& snippet) {
667 return snippet->id() == snippet_id; 670 return snippet->id() == snippet_id;
668 }); 671 });
669 if (it == snippets_.end()) { 672
670 callback.Run(MakeUniqueID(provided_category_, snippet_id), gfx::Image()); 673 if (it == snippets_.end() ||
674 !thumbnail_requests_throttler_.DemandQuotaForRequest(
675 /*interactive_request=*/true)) {
676 // Return an empty image. Directly, this is never synchronous with the
677 // original FetchSuggestionImage() call - an asynchronous database query has
678 // happened in the meantime.
679 OnSnippetImageDecodedFromNetwork(callback, snippet_id, gfx::Image());
671 return; 680 return;
672 } 681 }
673 682
674 const NTPSnippet& snippet = *it->get(); 683 const NTPSnippet& snippet = *it->get();
684
685 // The image fetcher calls OnImageDataFetched() with the raw data (this object
686 // is an ImageFetcherDelegate) and then also
687 // OnSnippetImageDecodedFromNetwork() after the raw data gets decoded.
675 image_fetcher_->StartOrQueueNetworkRequest( 688 image_fetcher_->StartOrQueueNetworkRequest(
676 snippet.id(), snippet.salient_image_url(), callback); 689 snippet.id(), snippet.salient_image_url(),
690 base::Bind(&NTPSnippetsService::OnSnippetImageDecodedFromNetwork,
691 base::Unretained(this), callback));
692 }
693
694 void NTPSnippetsService::OnSnippetImageDecodedFromNetwork(
695 const ImageFetchedCallback& callback,
696 const std::string& snippet_id,
697 const gfx::Image& image) {
698 callback.Run(MakeUniqueID(provided_category_, snippet_id), image);
677 } 699 }
678 700
679 void NTPSnippetsService::EnterStateEnabled(bool fetch_snippets) { 701 void NTPSnippetsService::EnterStateEnabled(bool fetch_snippets) {
680 if (fetch_snippets) 702 if (fetch_snippets)
681 FetchSnippets(/*force_request=*/false); 703 FetchSnippets(/*force_request=*/false);
682 704
683 // FetchSnippets should set the status to |AVAILABLE_LOADING| if relevant, 705 // FetchSnippets should set the status to |AVAILABLE_LOADING| if relevant,
684 // otherwise we transition to |AVAILABLE| here. 706 // otherwise we transition to |AVAILABLE| here.
685 if (category_status_ != CategoryStatus::AVAILABLE_LOADING) 707 if (category_status_ != CategoryStatus::AVAILABLE_LOADING)
686 UpdateCategoryStatus(CategoryStatus::AVAILABLE); 708 UpdateCategoryStatus(CategoryStatus::AVAILABLE);
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
813 void NTPSnippetsService::UpdateCategoryStatus(CategoryStatus status) { 835 void NTPSnippetsService::UpdateCategoryStatus(CategoryStatus status) {
814 if (status == category_status_) 836 if (status == category_status_)
815 return; 837 return;
816 838
817 category_status_ = status; 839 category_status_ = status;
818 observer()->OnCategoryStatusChanged(this, provided_category_, 840 observer()->OnCategoryStatusChanged(this, provided_category_,
819 category_status_); 841 category_status_);
820 } 842 }
821 843
822 } // namespace ntp_snippets 844 } // namespace ntp_snippets
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698