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

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

Issue 2377663002: [NTP Snippets] Introduce ContentSuggestion::ID (Closed)
Patch Set: . Created 4 years, 2 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 303 matching lines...) Expand 10 before | Expand all | Expand 10 after
314 314
315 CategoryInfo NTPSnippetsService::GetCategoryInfo(Category category) { 315 CategoryInfo NTPSnippetsService::GetCategoryInfo(Category category) {
316 DCHECK(categories_.find(category) != categories_.end()); 316 DCHECK(categories_.find(category) != categories_.end());
317 const CategoryContent& content = categories_[category]; 317 const CategoryContent& content = categories_[category];
318 return CategoryInfo(content.localized_title, 318 return CategoryInfo(content.localized_title,
319 ContentSuggestionsCardLayout::FULL_CARD, 319 ContentSuggestionsCardLayout::FULL_CARD,
320 /* has_more_button */ false, 320 /* has_more_button */ false,
321 /* show_if_empty */ true); 321 /* show_if_empty */ true);
322 } 322 }
323 323
324 void NTPSnippetsService::DismissSuggestion(const std::string& suggestion_id) { 324 void NTPSnippetsService::DismissSuggestion(
325 const ContentSuggestion::ID& suggestion_id) {
325 if (!ready()) 326 if (!ready())
326 return; 327 return;
327 328
328 Category category = GetCategoryFromUniqueID(suggestion_id); 329 DCHECK(categories_.find(suggestion_id.category()) != categories_.end());
Bernhard Bauer 2016/09/28 09:45:33 Nit: Using base::Contains() for this (from base/st
Marc Treib 2016/09/28 11:14:09 Done.
329 std::string snippet_id = GetWithinCategoryIDFromUniqueID(suggestion_id);
330 330
331 DCHECK(categories_.find(category) != categories_.end()); 331 CategoryContent* content = &categories_[suggestion_id.category()];
332 332 auto it = std::find_if(
333 CategoryContent* content = &categories_[category]; 333 content->snippets.begin(), content->snippets.end(),
334 auto it = 334 [&suggestion_id](const std::unique_ptr<NTPSnippet>& snippet) {
335 std::find_if(content->snippets.begin(), content->snippets.end(), 335 return snippet->id() == suggestion_id.within_category_id();
336 [&snippet_id](const std::unique_ptr<NTPSnippet>& snippet) { 336 });
337 return snippet->id() == snippet_id;
338 });
339 if (it == content->snippets.end()) 337 if (it == content->snippets.end())
340 return; 338 return;
341 339
342 (*it)->set_dismissed(true); 340 (*it)->set_dismissed(true);
343 341
344 database_->SaveSnippet(**it); 342 database_->SaveSnippet(**it);
345 database_->DeleteImage(snippet_id); 343 database_->DeleteImage(suggestion_id.within_category_id());
346 344
347 content->dismissed.push_back(std::move(*it)); 345 content->dismissed.push_back(std::move(*it));
348 content->snippets.erase(it); 346 content->snippets.erase(it);
349 } 347 }
350 348
351 void NTPSnippetsService::FetchSuggestionImage( 349 void NTPSnippetsService::FetchSuggestionImage(
352 const std::string& suggestion_id, 350 const ContentSuggestion::ID& suggestion_id,
353 const ImageFetchedCallback& callback) { 351 const ImageFetchedCallback& callback) {
354 std::string snippet_id = GetWithinCategoryIDFromUniqueID(suggestion_id);
355 database_->LoadImage( 352 database_->LoadImage(
356 snippet_id, 353 suggestion_id.within_category_id(),
357 base::Bind(&NTPSnippetsService::OnSnippetImageFetchedFromDatabase, 354 base::Bind(&NTPSnippetsService::OnSnippetImageFetchedFromDatabase,
358 base::Unretained(this), callback, suggestion_id)); 355 base::Unretained(this), callback, suggestion_id));
359 } 356 }
360 357
361 void NTPSnippetsService::ClearHistory( 358 void NTPSnippetsService::ClearHistory(
362 base::Time begin, 359 base::Time begin,
363 base::Time end, 360 base::Time end,
364 const base::Callback<bool(const GURL& url)>& filter) { 361 const base::Callback<bool(const GURL& url)>& filter) {
365 // Both time range and the filter are ignored and all suggestions are removed, 362 // Both time range and the filter are ignored and all suggestions are removed,
366 // because it is not known which history entries were used for the suggestions 363 // because it is not known which history entries were used for the suggestions
(...skipping 26 matching lines...) Expand all
393 void NTPSnippetsService::GetDismissedSuggestionsForDebugging( 390 void NTPSnippetsService::GetDismissedSuggestionsForDebugging(
394 Category category, 391 Category category,
395 const DismissedSuggestionsCallback& callback) { 392 const DismissedSuggestionsCallback& callback) {
396 DCHECK(categories_.find(category) != categories_.end()); 393 DCHECK(categories_.find(category) != categories_.end());
397 394
398 std::vector<ContentSuggestion> result; 395 std::vector<ContentSuggestion> result;
399 const CategoryContent& content = categories_[category]; 396 const CategoryContent& content = categories_[category];
400 for (const std::unique_ptr<NTPSnippet>& snippet : content.dismissed) { 397 for (const std::unique_ptr<NTPSnippet>& snippet : content.dismissed) {
401 if (!snippet->is_complete()) 398 if (!snippet->is_complete())
402 continue; 399 continue;
403 ContentSuggestion suggestion(MakeUniqueID(category, snippet->id()), 400 ContentSuggestion suggestion(category, snippet->id(),
404 snippet->best_source().url); 401 snippet->best_source().url);
405 suggestion.set_amp_url(snippet->best_source().amp_url); 402 suggestion.set_amp_url(snippet->best_source().amp_url);
406 suggestion.set_title(base::UTF8ToUTF16(snippet->title())); 403 suggestion.set_title(base::UTF8ToUTF16(snippet->title()));
407 suggestion.set_snippet_text(base::UTF8ToUTF16(snippet->snippet())); 404 suggestion.set_snippet_text(base::UTF8ToUTF16(snippet->snippet()));
408 suggestion.set_publish_date(snippet->publish_date()); 405 suggestion.set_publish_date(snippet->publish_date());
409 suggestion.set_publisher_name( 406 suggestion.set_publisher_name(
410 base::UTF8ToUTF16(snippet->best_source().publisher_name)); 407 base::UTF8ToUTF16(snippet->best_source().publisher_name));
411 suggestion.set_score(snippet->score()); 408 suggestion.set_score(snippet->score());
412 result.emplace_back(std::move(suggestion)); 409 result.emplace_back(std::move(suggestion));
413 } 410 }
(...skipping 30 matching lines...) Expand all
444 441
445 // static 442 // static
446 int NTPSnippetsService::GetMaxSnippetCountForTesting() { 443 int NTPSnippetsService::GetMaxSnippetCountForTesting() {
447 return kMaxSnippetCount; 444 return kMaxSnippetCount;
448 } 445 }
449 446
450 //////////////////////////////////////////////////////////////////////////////// 447 ////////////////////////////////////////////////////////////////////////////////
451 // Private methods 448 // Private methods
452 449
453 GURL NTPSnippetsService::FindSnippetImageUrl( 450 GURL NTPSnippetsService::FindSnippetImageUrl(
454 Category category, 451 const ContentSuggestion::ID& suggestion_id) const {
455 const std::string& snippet_id) const { 452 DCHECK(categories_.find(suggestion_id.category()) != categories_.end());
456 DCHECK(categories_.find(category) != categories_.end());
457 453
458 const CategoryContent& content = categories_.at(category); 454 const CategoryContent& content = categories_.at(suggestion_id.category());
459 // Search for the snippet in current and archived snippets. 455 const NTPSnippet* snippet =
460 auto it = 456 content.FindSnippet(suggestion_id.within_category_id());
461 std::find_if(content.snippets.begin(), content.snippets.end(), 457 if (!snippet)
462 [&snippet_id](const std::unique_ptr<NTPSnippet>& snippet) { 458 return GURL();
463 return snippet->id() == snippet_id; 459 return snippet->salient_image_url();
464 });
465 if (it != content.snippets.end())
466 return (*it)->salient_image_url();
467
468 it = std::find_if(content.archived.begin(), content.archived.end(),
469 [&snippet_id](const std::unique_ptr<NTPSnippet>& snippet) {
470 return snippet->id() == snippet_id;
471 });
472 if (it != content.archived.end())
473 return (*it)->salient_image_url();
474
475 return GURL();
476 } 460 }
477 461
478 // image_fetcher::ImageFetcherDelegate implementation. 462 // image_fetcher::ImageFetcherDelegate implementation.
479 void NTPSnippetsService::OnImageDataFetched(const std::string& suggestion_id, 463 void NTPSnippetsService::OnImageDataFetched(
480 const std::string& image_data) { 464 const std::string& within_category_id,
465 const std::string& image_data) {
481 if (image_data.empty()) 466 if (image_data.empty())
482 return; 467 return;
483 468
484 Category category = GetCategoryFromUniqueID(suggestion_id);
485 std::string snippet_id = GetWithinCategoryIDFromUniqueID(suggestion_id);
486
487 if (categories_.find(category) == categories_.end())
488 return;
489
490 // Only save the image if the corresponding snippet still exists. 469 // Only save the image if the corresponding snippet still exists.
491 if (FindSnippetImageUrl(category, snippet_id).is_empty()) 470 bool found = false;
471 for (const std::pair<const Category, CategoryContent>& entry : categories_) {
472 if (entry.second.FindSnippet(within_category_id)) {
473 found = true;
474 break;
475 }
476 }
477 if (!found)
492 return; 478 return;
493 479
494 // Only cache the data in the DB, the actual serving is done in the callback 480 // Only cache the data in the DB, the actual serving is done in the callback
495 // provided to |image_fetcher_| (OnSnippetImageDecodedFromNetwork()). 481 // provided to |image_fetcher_| (OnSnippetImageDecodedFromNetwork()).
496 database_->SaveImage(snippet_id, image_data); 482 database_->SaveImage(within_category_id, image_data);
497 } 483 }
498 484
499 void NTPSnippetsService::OnDatabaseLoaded(NTPSnippet::PtrVector snippets) { 485 void NTPSnippetsService::OnDatabaseLoaded(NTPSnippet::PtrVector snippets) {
500 if (state_ == State::ERROR_OCCURRED) 486 if (state_ == State::ERROR_OCCURRED)
501 return; 487 return;
502 DCHECK(state_ == State::NOT_INITED); 488 DCHECK(state_ == State::NOT_INITED);
503 DCHECK_EQ(1u, categories_.size()); // Only articles category, so far. 489 DCHECK_EQ(1u, categories_.size()); // Only articles category, so far.
504 DCHECK(categories_.find(articles_category_) != categories_.end()); 490 DCHECK(categories_.find(articles_category_) != categories_.end());
505 491
506 // TODO(sfiera): support non-article categories in database. 492 // TODO(sfiera): support non-article categories in database.
(...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after
812 } 798 }
813 } 799 }
814 800
815 for (Category category : categories_to_erase) { 801 for (Category category : categories_to_erase) {
816 categories_.erase(category); 802 categories_.erase(category);
817 } 803 }
818 } 804 }
819 805
820 void NTPSnippetsService::OnSnippetImageFetchedFromDatabase( 806 void NTPSnippetsService::OnSnippetImageFetchedFromDatabase(
821 const ImageFetchedCallback& callback, 807 const ImageFetchedCallback& callback,
822 const std::string& suggestion_id, 808 const ContentSuggestion::ID& suggestion_id,
823 std::string data) { 809 std::string data) {
824 // |image_decoder_| is null in tests. 810 // |image_decoder_| is null in tests.
825 if (image_decoder_ && !data.empty()) { 811 if (image_decoder_ && !data.empty()) {
826 image_decoder_->DecodeImage( 812 image_decoder_->DecodeImage(
827 data, base::Bind(&NTPSnippetsService::OnSnippetImageDecodedFromDatabase, 813 data, base::Bind(&NTPSnippetsService::OnSnippetImageDecodedFromDatabase,
828 base::Unretained(this), callback, suggestion_id)); 814 base::Unretained(this), callback, suggestion_id));
829 return; 815 return;
830 } 816 }
831 817
832 // Fetching from the DB failed; start a network fetch. 818 // Fetching from the DB failed; start a network fetch.
833 FetchSnippetImageFromNetwork(suggestion_id, callback); 819 FetchSnippetImageFromNetwork(suggestion_id, callback);
834 } 820 }
835 821
836 void NTPSnippetsService::OnSnippetImageDecodedFromDatabase( 822 void NTPSnippetsService::OnSnippetImageDecodedFromDatabase(
837 const ImageFetchedCallback& callback, 823 const ImageFetchedCallback& callback,
838 const std::string& suggestion_id, 824 const ContentSuggestion::ID& suggestion_id,
839 const gfx::Image& image) { 825 const gfx::Image& image) {
840 if (!image.IsEmpty()) { 826 if (!image.IsEmpty()) {
841 callback.Run(image); 827 callback.Run(image);
842 return; 828 return;
843 } 829 }
844 830
845 // If decoding the image failed, delete the DB entry. 831 // If decoding the image failed, delete the DB entry.
846 std::string snippet_id = GetWithinCategoryIDFromUniqueID(suggestion_id); 832 database_->DeleteImage(suggestion_id.within_category_id());
847 database_->DeleteImage(snippet_id);
848 833
849 FetchSnippetImageFromNetwork(suggestion_id, callback); 834 FetchSnippetImageFromNetwork(suggestion_id, callback);
850 } 835 }
851 836
852 void NTPSnippetsService::FetchSnippetImageFromNetwork( 837 void NTPSnippetsService::FetchSnippetImageFromNetwork(
853 const std::string& suggestion_id, 838 const ContentSuggestion::ID& suggestion_id,
854 const ImageFetchedCallback& callback) { 839 const ImageFetchedCallback& callback) {
855 Category category = GetCategoryFromUniqueID(suggestion_id); 840 if (categories_.find(suggestion_id.category()) == categories_.end()) {
856 std::string snippet_id = GetWithinCategoryIDFromUniqueID(suggestion_id); 841 OnSnippetImageDecodedFromNetwork(
857 842 callback, suggestion_id.within_category_id(), gfx::Image());
858 if (categories_.find(category) == categories_.end()) {
859 OnSnippetImageDecodedFromNetwork(callback, suggestion_id, gfx::Image());
860 return; 843 return;
861 } 844 }
862 845
863 GURL image_url = FindSnippetImageUrl(category, snippet_id); 846 GURL image_url = FindSnippetImageUrl(suggestion_id);
864 847
865 if (image_url.is_empty() || 848 if (image_url.is_empty() ||
866 !thumbnail_requests_throttler_.DemandQuotaForRequest( 849 !thumbnail_requests_throttler_.DemandQuotaForRequest(
867 /*interactive_request=*/true)) { 850 /*interactive_request=*/true)) {
868 // Return an empty image. Directly, this is never synchronous with the 851 // Return an empty image. Directly, this is never synchronous with the
869 // original FetchSuggestionImage() call - an asynchronous database query has 852 // original FetchSuggestionImage() call - an asynchronous database query has
870 // happened in the meantime. 853 // happened in the meantime.
871 OnSnippetImageDecodedFromNetwork(callback, suggestion_id, gfx::Image()); 854 OnSnippetImageDecodedFromNetwork(
855 callback, suggestion_id.within_category_id(), gfx::Image());
872 return; 856 return;
873 } 857 }
874 858
875 image_fetcher_->StartOrQueueNetworkRequest( 859 image_fetcher_->StartOrQueueNetworkRequest(
876 suggestion_id, image_url, 860 suggestion_id.within_category_id(), image_url,
877 base::Bind(&NTPSnippetsService::OnSnippetImageDecodedFromNetwork, 861 base::Bind(&NTPSnippetsService::OnSnippetImageDecodedFromNetwork,
878 base::Unretained(this), callback)); 862 base::Unretained(this), callback));
879 } 863 }
880 864
881 void NTPSnippetsService::OnSnippetImageDecodedFromNetwork( 865 void NTPSnippetsService::OnSnippetImageDecodedFromNetwork(
882 const ImageFetchedCallback& callback, 866 const ImageFetchedCallback& callback,
883 const std::string& suggestion_id, 867 const std::string& within_category_id,
884 const gfx::Image& image) { 868 const gfx::Image& image) {
885 callback.Run(image); 869 callback.Run(image);
886 } 870 }
887 871
888 void NTPSnippetsService::EnterStateReady() { 872 void NTPSnippetsService::EnterStateReady() {
889 if (nuke_when_initialized_) { 873 if (nuke_when_initialized_) {
890 NukeAllSnippets(); 874 NukeAllSnippets();
891 nuke_when_initialized_ = false; 875 nuke_when_initialized_ = false;
892 } 876 }
893 877
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
1019 const CategoryContent& content = item.second; 1003 const CategoryContent& content = item.second;
1020 1004
1021 std::vector<ContentSuggestion> result; 1005 std::vector<ContentSuggestion> result;
1022 for (const std::unique_ptr<NTPSnippet>& snippet : content.snippets) { 1006 for (const std::unique_ptr<NTPSnippet>& snippet : content.snippets) {
1023 // TODO(sfiera): if a snippet is not going to be displayed, move it 1007 // TODO(sfiera): if a snippet is not going to be displayed, move it
1024 // directly to content.dismissed on fetch. Otherwise, we might prune 1008 // directly to content.dismissed on fetch. Otherwise, we might prune
1025 // other snippets to get down to kMaxSnippetCount, only to hide one of the 1009 // other snippets to get down to kMaxSnippetCount, only to hide one of the
1026 // incomplete ones we kept. 1010 // incomplete ones we kept.
1027 if (!snippet->is_complete()) 1011 if (!snippet->is_complete())
1028 continue; 1012 continue;
1029 ContentSuggestion suggestion(MakeUniqueID(category, snippet->id()), 1013 ContentSuggestion suggestion(category, snippet->id(),
1030 snippet->best_source().url); 1014 snippet->best_source().url);
1031 suggestion.set_amp_url(snippet->best_source().amp_url); 1015 suggestion.set_amp_url(snippet->best_source().amp_url);
1032 suggestion.set_title(base::UTF8ToUTF16(snippet->title())); 1016 suggestion.set_title(base::UTF8ToUTF16(snippet->title()));
1033 suggestion.set_snippet_text(base::UTF8ToUTF16(snippet->snippet())); 1017 suggestion.set_snippet_text(base::UTF8ToUTF16(snippet->snippet()));
1034 suggestion.set_publish_date(snippet->publish_date()); 1018 suggestion.set_publish_date(snippet->publish_date());
1035 suggestion.set_publisher_name( 1019 suggestion.set_publisher_name(
1036 base::UTF8ToUTF16(snippet->best_source().publisher_name)); 1020 base::UTF8ToUTF16(snippet->best_source().publisher_name));
1037 suggestion.set_score(snippet->score()); 1021 suggestion.set_score(snippet->score());
1038 result.emplace_back(std::move(suggestion)); 1022 result.emplace_back(std::move(suggestion));
1039 } 1023 }
(...skipping 17 matching lines...) Expand all
1057 content.status = status; 1041 content.status = status;
1058 observer()->OnCategoryStatusChanged(this, category, content.status); 1042 observer()->OnCategoryStatusChanged(this, category, content.status);
1059 } 1043 }
1060 1044
1061 void NTPSnippetsService::UpdateAllCategoryStatus(CategoryStatus status) { 1045 void NTPSnippetsService::UpdateAllCategoryStatus(CategoryStatus status) {
1062 for (const auto& category : categories_) { 1046 for (const auto& category : categories_) {
1063 UpdateCategoryStatus(category.first, status); 1047 UpdateCategoryStatus(category.first, status);
1064 } 1048 }
1065 } 1049 }
1066 1050
1051 const NTPSnippet* NTPSnippetsService::CategoryContent::FindSnippet(
1052 const std::string& within_category_id) const {
1053 // Search for the snippet in current and archived snippets.
1054 auto it = std::find_if(
1055 snippets.begin(), snippets.end(),
1056 [&within_category_id](const std::unique_ptr<NTPSnippet>& snippet) {
1057 return snippet->id() == within_category_id;
1058 });
1059 if (it != snippets.end())
1060 return it->get();
1061
1062 it = std::find_if(
1063 archived.begin(), archived.end(),
1064 [&within_category_id](const std::unique_ptr<NTPSnippet>& snippet) {
1065 return snippet->id() == within_category_id;
1066 });
1067 if (it != archived.end())
1068 return it->get();
1069
1070 return nullptr;
1071 }
1072
1067 NTPSnippetsService::CategoryContent::CategoryContent() = default; 1073 NTPSnippetsService::CategoryContent::CategoryContent() = default;
1068 NTPSnippetsService::CategoryContent::CategoryContent(CategoryContent&&) = 1074 NTPSnippetsService::CategoryContent::CategoryContent(CategoryContent&&) =
1069 default; 1075 default;
1070 NTPSnippetsService::CategoryContent::~CategoryContent() = default; 1076 NTPSnippetsService::CategoryContent::~CategoryContent() = default;
1071 NTPSnippetsService::CategoryContent& NTPSnippetsService::CategoryContent:: 1077 NTPSnippetsService::CategoryContent& NTPSnippetsService::CategoryContent::
1072 operator=(CategoryContent&&) = default; 1078 operator=(CategoryContent&&) = default;
1073 1079
1074 } // namespace ntp_snippets 1080 } // namespace ntp_snippets
OLDNEW
« no previous file with comments | « components/ntp_snippets/ntp_snippets_service.h ('k') | components/ntp_snippets/ntp_snippets_service_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698