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

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

Issue 2421463002: FetchMore functionality backend (Closed)
Patch Set: NTBR. Rebasing a lot. Created 4 years, 1 month 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/remote/ntp_snippets_service.h" 5 #include "components/ntp_snippets/remote/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 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
150 } 150 }
151 151
152 void RemoveNullPointers(NTPSnippet::PtrVector* snippets) { 152 void RemoveNullPointers(NTPSnippet::PtrVector* snippets) {
153 snippets->erase( 153 snippets->erase(
154 std::remove_if( 154 std::remove_if(
155 snippets->begin(), snippets->end(), 155 snippets->begin(), snippets->end(),
156 [](const std::unique_ptr<NTPSnippet>& snippet) { return !snippet; }), 156 [](const std::unique_ptr<NTPSnippet>& snippet) { return !snippet; }),
157 snippets->end()); 157 snippets->end());
158 } 158 }
159 159
160 void AssignExpiryAndPublishDates(NTPSnippet::PtrVector* snippets) {
161 for (std::unique_ptr<NTPSnippet>& snippet : *snippets) {
162 if (snippet->publish_date().is_null())
163 snippet->set_publish_date(base::Time::Now());
164 if (snippet->expiry_date().is_null()) {
165 snippet->set_expiry_date(
166 snippet->publish_date() +
167 base::TimeDelta::FromMinutes(kDefaultExpiryTimeMins));
168 }
169 }
170 }
171
172 void RemoveIncompleteSnippets(NTPSnippet::PtrVector* snippets) {
173 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
174 switches::kAddIncompleteSnippets)) {
175 return;
176 }
177 int num_snippets = snippets->size();
178 // Remove snippets that do not have all the info we need to display it to
179 // the user.
180 snippets->erase(
181 std::remove_if(snippets->begin(), snippets->end(),
182 [](const std::unique_ptr<NTPSnippet>& snippet) {
183 return !snippet->is_complete();
184 }),
185 snippets->end());
186 int num_snippets_dismissed = num_snippets - snippets->size();
vitaliii 2016/11/01 23:29:57 s/dismissed/removed? "dismissed" is usually used i
fhorschig 2016/11/02 05:05:27 Done in CL 2466863003.
187 UMA_HISTOGRAM_BOOLEAN("NewTabPage.Snippets.IncompleteSnippetsAfterFetch",
188 num_snippets_dismissed > 0);
189 if (num_snippets_dismissed > 0) {
190 UMA_HISTOGRAM_SPARSE_SLOWLY("NewTabPage.Snippets.NumIncompleteSnippets",
191 num_snippets_dismissed);
192 }
193 }
194
195 NTPSnippetsService::FetchedMoreCallback NullCallback() {
196 return NTPSnippetsService::FetchedMoreCallback();
197 }
198
160 } // namespace 199 } // namespace
161 200
162 NTPSnippetsService::NTPSnippetsService( 201 NTPSnippetsService::NTPSnippetsService(
163 Observer* observer, 202 Observer* observer,
164 CategoryFactory* category_factory, 203 CategoryFactory* category_factory,
165 PrefService* pref_service, 204 PrefService* pref_service,
166 const std::string& application_language_code, 205 const std::string& application_language_code,
167 const UserClassifier* user_classifier, 206 const UserClassifier* user_classifier,
168 NTPSnippetsScheduler* scheduler, 207 NTPSnippetsScheduler* scheduler,
169 std::unique_ptr<NTPSnippetsFetcher> snippets_fetcher, 208 std::unique_ptr<NTPSnippetsFetcher> snippets_fetcher,
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
236 void NTPSnippetsService::FetchSnippets(bool interactive_request) { 275 void NTPSnippetsService::FetchSnippets(bool interactive_request) {
237 if (ready()) 276 if (ready())
238 FetchSnippetsFromHosts(std::set<std::string>(), interactive_request); 277 FetchSnippetsFromHosts(std::set<std::string>(), interactive_request);
239 else 278 else
240 fetch_when_ready_ = true; 279 fetch_when_ready_ = true;
241 } 280 }
242 281
243 void NTPSnippetsService::FetchSnippetsFromHosts( 282 void NTPSnippetsService::FetchSnippetsFromHosts(
244 const std::set<std::string>& hosts, 283 const std::set<std::string>& hosts,
245 bool interactive_request) { 284 bool interactive_request) {
285 FetchSnippetsFromHostsImpl(hosts, interactive_request,
286 /*fetch_more=*/false,
287 base::Optional<Category>(),
288 NullCallback());
vitaliii 2016/11/01 23:29:57 Actually writing here |NTPSnippetsService::Fetched
fhorschig 2016/11/02 05:05:27 Done in 2446163005.
289 }
290
291 void NTPSnippetsService::FetchMore(const Category& category,
292 const FetchedMoreCallback& callback) {
293 FetchSnippetsFromHostsImpl(std::set<std::string>(),
294 /*interactive_request=*/true,
295 /*fetch_more=*/true,
296 base::Optional<Category>(category),
297 callback);
298 }
299
300 void NTPSnippetsService::FetchSnippetsFromHostsImpl(
301 const std::set<std::string>& hosts,
302 bool interactive_request,
303 bool fetch_more,
304 base::Optional<Category> exclusive_category,
305 const FetchedMoreCallback& callback) {
246 if (!ready()) 306 if (!ready())
247 return; 307 return;
248 308
249 // Empty categories are marked as loading; others are unchanged.
250 for (const auto& item : categories_) {
251 Category category = item.first;
252 const CategoryContent& content = item.second;
253 if (content.snippets.empty())
254 UpdateCategoryStatus(category, CategoryStatus::AVAILABLE_LOADING);
255 }
256
257 NTPSnippetsFetcher::Params params; 309 NTPSnippetsFetcher::Params params;
258 params.language_code = application_language_code_; 310 params.language_code = application_language_code_;
259 params.count_to_fetch = kMaxSnippetCount; 311 params.count_to_fetch = kMaxSnippetCount;
260 params.hosts = hosts; 312 params.hosts = hosts;
261 params.interactive_request = interactive_request; 313 params.interactive_request = interactive_request;
314 params.exclusive_category = exclusive_category;
315 params.excluded_ids = CollectIdsToExclude(fetch_more);
316 params.snippets_available_callback =
317 base::BindOnce(&NTPSnippetsService::OnFetchFinished,
318 base::Unretained(this),
319 fetch_more,
320 std::move(callback));
321
322 MarkEmptyCategoriesAsLoading(&params);
323
324 snippets_fetcher_->FetchSnippets(params);
325 }
326
327 std::set<std::string> NTPSnippetsService::CollectIdsToExclude(bool fetch_more) {
328 std::set<std::string> ids;
262 for (const auto& item : categories_) { 329 for (const auto& item : categories_) {
263 const CategoryContent& content = item.second; 330 const CategoryContent& content = item.second;
264 for (const auto& snippet : content.dismissed) 331 for (const auto& snippet : content.dismissed)
265 params.excluded_ids.insert(snippet->id()); 332 ids.insert(snippet->id());
333 if (!fetch_more)
334 continue;
335 for (const auto& snippet : content.archived)
336 ids.insert(snippet->id());
337 for (const auto& snippet : content.snippets)
338 ids.insert(snippet->id());
266 } 339 }
267 snippets_fetcher_->FetchSnippets(params); 340 return ids;
341 }
342
343 void NTPSnippetsService::MarkEmptyCategoriesAsLoading(
344 NTPSnippetsFetcher::Params* params) {
345 for (const auto& item : categories_) {
346 Category category = item.first;
347 const CategoryContent& content = item.second;
348 for (const auto& snippet : content.dismissed)
349 params->excluded_ids.insert(snippet->id());
vitaliii 2016/11/01 23:29:57 I cannot understand why this is done here. First,
fhorschig 2016/11/02 05:05:27 This is a false merge. It is completely dropped la
350 if (content.snippets.empty())
351 UpdateCategoryStatus(category, CategoryStatus::AVAILABLE_LOADING);
352 }
268 } 353 }
269 354
270 void NTPSnippetsService::RescheduleFetching(bool force) { 355 void NTPSnippetsService::RescheduleFetching(bool force) {
271 // The scheduler only exists on Android so far, it's null on other platforms. 356 // The scheduler only exists on Android so far, it's null on other platforms.
272 if (!scheduler_) 357 if (!scheduler_)
273 return; 358 return;
274 359
275 if (ready()) { 360 if (ready()) {
276 base::TimeDelta old_interval_wifi = 361 base::TimeDelta old_interval_wifi =
277 base::TimeDelta::FromInternalValue(pref_service_->GetInt64( 362 base::TimeDelta::FromInternalValue(pref_service_->GetInt64(
(...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after
522 ClearOrphanedImages(); 607 ClearOrphanedImages();
523 FinishInitialization(); 608 FinishInitialization();
524 } 609 }
525 610
526 void NTPSnippetsService::OnDatabaseError() { 611 void NTPSnippetsService::OnDatabaseError() {
527 EnterState(State::ERROR_OCCURRED); 612 EnterState(State::ERROR_OCCURRED);
528 UpdateAllCategoryStatus(CategoryStatus::LOADING_ERROR); 613 UpdateAllCategoryStatus(CategoryStatus::LOADING_ERROR);
529 } 614 }
530 615
531 void NTPSnippetsService::OnFetchFinished( 616 void NTPSnippetsService::OnFetchFinished(
617 bool fetched_more,
618 const FetchedMoreCallback& fetched_more_callback,
532 NTPSnippetsFetcher::OptionalFetchedCategories fetched_categories) { 619 NTPSnippetsFetcher::OptionalFetchedCategories fetched_categories) {
533 if (!ready()) 620 if (!ready())
534 return; 621 return;
535 622
536 // Mark all categories as not provided by the server in the latest fetch. The 623 // Mark all categories as not provided by the server in the latest fetch. The
537 // ones we got will be marked again below. 624 // ones we got will be marked again below.
538 for (auto& item : categories_) { 625 for (auto& item : categories_) {
539 CategoryContent* content = &item.second; 626 CategoryContent* content = &item.second;
540 content->provided_by_server = false; 627 content->provided_by_server = false;
541 } 628 }
(...skipping 24 matching lines...) Expand all
566 categories_[category].provided_by_server = true; 653 categories_[category].provided_by_server = true;
567 654
568 // TODO(tschumann): Remove this histogram once we only talk to the content 655 // TODO(tschumann): Remove this histogram once we only talk to the content
569 // suggestions cloud backend. 656 // suggestions cloud backend.
570 if (category == articles_category_) { 657 if (category == articles_category_) {
571 UMA_HISTOGRAM_SPARSE_SLOWLY( 658 UMA_HISTOGRAM_SPARSE_SLOWLY(
572 "NewTabPage.Snippets.NumArticlesFetched", 659 "NewTabPage.Snippets.NumArticlesFetched",
573 std::min(fetched_category.snippets.size(), 660 std::min(fetched_category.snippets.size(),
574 static_cast<size_t>(kMaxSnippetCount + 1))); 661 static_cast<size_t>(kMaxSnippetCount + 1)));
575 } 662 }
576 ReplaceSnippets(category, std::move(fetched_category.snippets)); 663 IncludeSnippets(category, std::move(fetched_category.snippets),
664 /*replace_snippets=*/!fetched_more);
577 } 665 }
578 } 666 }
579 667
580 // We might have gotten new categories (or updated the titles of existing 668 // We might have gotten new categories (or updated the titles of existing
581 // ones), so update the pref. 669 // ones), so update the pref.
582 StoreCategoriesToPrefs(); 670 StoreCategoriesToPrefs();
583 671
584 for (const auto& item : categories_) { 672 for (const auto& item : categories_) {
585 Category category = item.first; 673 Category category = item.first;
586 UpdateCategoryStatus(category, CategoryStatus::AVAILABLE); 674 UpdateCategoryStatus(category, CategoryStatus::AVAILABLE);
587 // TODO(sfiera): notify only when a category changed above. 675 // TODO(sfiera): notify only when a category changed above.
588 NotifyNewSuggestions(category); 676 NotifyNewSuggestionsOrInvokeCallback(category, fetched_more_callback);
589 } 677 }
590 678
591 // TODO(sfiera): equivalent metrics for non-articles. 679 // TODO(sfiera): equivalent metrics for non-articles.
592 const CategoryContent& content = categories_[articles_category_]; 680 const CategoryContent& content = categories_[articles_category_];
593 UMA_HISTOGRAM_SPARSE_SLOWLY("NewTabPage.Snippets.NumArticles", 681 UMA_HISTOGRAM_SPARSE_SLOWLY("NewTabPage.Snippets.NumArticles",
594 content.snippets.size()); 682 content.snippets.size());
595 if (content.snippets.empty() && !content.dismissed.empty()) { 683 if (content.snippets.empty() && !content.dismissed.empty()) {
596 UMA_HISTOGRAM_COUNTS("NewTabPage.Snippets.NumArticlesZeroDueToDiscarded", 684 UMA_HISTOGRAM_COUNTS("NewTabPage.Snippets.NumArticlesZeroDueToDiscarded",
597 content.dismissed.size()); 685 content.dismissed.size());
598 } 686 }
599 687
600 // Reschedule after a successful fetch. This resets all currently scheduled 688 // Reschedule after a successful fetch. This resets all currently scheduled
601 // fetches, to make sure the fallback interval triggers only if no wifi fetch 689 // fetches, to make sure the fallback interval triggers only if no wifi fetch
602 // succeeded, and also that we don't do a background fetch immediately after 690 // succeeded, and also that we don't do a background fetch immediately after
603 // a user-initiated one. 691 // a user-initiated one.
604 if (fetched_categories) 692 if (fetched_categories)
605 RescheduleFetching(true); 693 RescheduleFetching(true);
606 } 694 }
607 695
608 void NTPSnippetsService::ArchiveSnippets(Category category, 696 void NTPSnippetsService::IncludeSnippets(const Category& category,
609 NTPSnippet::PtrVector* to_archive) { 697 NTPSnippet::PtrVector new_snippets,
610 CategoryContent* content = &categories_[category]; 698 bool replace_snippets) {
611 database_->DeleteSnippets(GetSnippetIDVector(*to_archive));
612 // Do not delete the thumbnail images as they are still handy on open NTPs.
613
614 // Archive previous snippets - move them at the beginning of the list.
615 content->archived.insert(content->archived.begin(),
616 std::make_move_iterator(to_archive->begin()),
617 std::make_move_iterator(to_archive->end()));
618 RemoveNullPointers(to_archive);
619
620 // If there are more archived snippets than we want to keep, delete the
621 // oldest ones by their fetch time (which are always in the back).
622 if (content->archived.size() > kMaxArchivedSnippetCount) {
623 NTPSnippet::PtrVector to_delete(
624 std::make_move_iterator(content->archived.begin() +
625 kMaxArchivedSnippetCount),
626 std::make_move_iterator(content->archived.end()));
627 content->archived.resize(kMaxArchivedSnippetCount);
628 database_->DeleteImages(GetSnippetIDVector(to_delete));
629 }
630 }
631
632 void NTPSnippetsService::ReplaceSnippets(Category category,
633 NTPSnippet::PtrVector new_snippets) {
634 DCHECK(ready()); 699 DCHECK(ready());
635 CategoryContent* content = &categories_[category]; 700 CategoryContent* content = &categories_[category];
636 701
637 // Remove new snippets that have been dismissed. 702 // Remove new snippets that have been dismissed.
638 EraseMatchingSnippets(&new_snippets, content->dismissed); 703 EraseMatchingSnippets(&new_snippets, content->dismissed);
639 704
640 // Fill in default publish/expiry dates where required. 705 AssignExpiryAndPublishDates(&new_snippets);
641 for (std::unique_ptr<NTPSnippet>& snippet : new_snippets) { 706 RemoveIncompleteSnippets(&new_snippets);
642 if (snippet->publish_date().is_null())
643 snippet->set_publish_date(base::Time::Now());
644 if (snippet->expiry_date().is_null()) {
645 snippet->set_expiry_date(
646 snippet->publish_date() +
647 base::TimeDelta::FromMinutes(kDefaultExpiryTimeMins));
648 }
649 }
650
651 if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
652 switches::kAddIncompleteSnippets)) {
653 int num_new_snippets = new_snippets.size();
654 // Remove snippets that do not have all the info we need to display it to
655 // the user.
656 new_snippets.erase(
657 std::remove_if(new_snippets.begin(), new_snippets.end(),
658 [](const std::unique_ptr<NTPSnippet>& snippet) {
659 return !snippet->is_complete();
660 }),
661 new_snippets.end());
662 int num_snippets_dismissed = num_new_snippets - new_snippets.size();
663 UMA_HISTOGRAM_BOOLEAN("NewTabPage.Snippets.IncompleteSnippetsAfterFetch",
664 num_snippets_dismissed > 0);
665 if (num_snippets_dismissed > 0) {
666 UMA_HISTOGRAM_SPARSE_SLOWLY("NewTabPage.Snippets.NumIncompleteSnippets",
667 num_snippets_dismissed);
668 }
669 }
670 707
671 // Do not touch the current set of snippets if the newly fetched one is empty. 708 // Do not touch the current set of snippets if the newly fetched one is empty.
672 if (new_snippets.empty()) 709 if (new_snippets.empty())
673 return; 710 return;
674 711
675 // It's entirely possible that the newly fetched snippets contain articles 712 // It's entirely possible that the newly fetched snippets contain articles
676 // that have been present before. 713 // that have been present before.
677 // Since archival removes snippets from the database (indexed by 714 // Since archival removes snippets from the database (indexed by
678 // snippet->id()), we need to make sure to only archive snippets that don't 715 // snippet->id()), we need to make sure to only archive snippets that don't
679 // appear with the same ID in the new suggestions (it's fine for additional 716 // appear with the same ID in the new suggestions (it's fine for additional
680 // IDs though). 717 // IDs though).
681 EraseByPrimaryID(&content->snippets, *GetSnippetIDVector(new_snippets)); 718 EraseByPrimaryID(&content->snippets, *GetSnippetIDVector(new_snippets));
682 ArchiveSnippets(category, &content->snippets);
683 719
684 // Save new articles to the DB. 720 SaveSnippets(category, std::move(new_snippets), replace_snippets);
721 }
722
723 void NTPSnippetsService::SaveSnippets(const Category& category,
724 NTPSnippet::PtrVector new_snippets,
725 bool replace_snippets) {
685 database_->SaveSnippets(new_snippets); 726 database_->SaveSnippets(new_snippets);
686 727
687 content->snippets = std::move(new_snippets); 728 CategoryContent* content = &categories_[category];
729
730 if (replace_snippets) {
731 ArchiveSnippets(category, &content->snippets);
732 content->snippets = std::move(new_snippets);
733 return;
734 }
735
736 content->snippets.insert(content->snippets.end(),
737 std::make_move_iterator(new_snippets.begin()),
738 std::make_move_iterator(new_snippets.end()));
688 } 739 }
689 740
741 void NTPSnippetsService::ArchiveSnippets(Category category,
742 NTPSnippet::PtrVector* to_archive) {
743 CategoryContent* content = &categories_[category];
744 database_->DeleteSnippets(GetSnippetIDVector(*to_archive));
745 // Do not delete the thumbnail images as they are still handy on open NTPs.
746
747 // Archive previous snippets - move them at the beginning of the list.
748 content->archived.insert(content->archived.begin(),
749 std::make_move_iterator(to_archive->begin()),
750 std::make_move_iterator(to_archive->end()));
751 RemoveNullPointers(to_archive);
752
753 // If there are more archived snippets than we want to keep, delete the
754 // oldest ones by their fetch time (which are always in the back).
755 if (content->archived.size() > kMaxArchivedSnippetCount) {
756 NTPSnippet::PtrVector to_delete(
757 std::make_move_iterator(content->archived.begin() +
758 kMaxArchivedSnippetCount),
759 std::make_move_iterator(content->archived.end()));
760 content->archived.resize(kMaxArchivedSnippetCount);
761 database_->DeleteImages(GetSnippetIDVector(to_delete));
762 }
763 }
690 void NTPSnippetsService::ClearExpiredDismissedSnippets() { 764 void NTPSnippetsService::ClearExpiredDismissedSnippets() {
691 std::vector<Category> categories_to_erase; 765 std::vector<Category> categories_to_erase;
692 766
693 const base::Time now = base::Time::Now(); 767 const base::Time now = base::Time::Now();
694 768
695 for (auto& item : categories_) { 769 for (auto& item : categories_) {
696 Category category = item.first; 770 Category category = item.first;
697 CategoryContent* content = &item.second; 771 CategoryContent* content = &item.second;
698 772
699 NTPSnippet::PtrVector to_delete; 773 NTPSnippet::PtrVector to_delete;
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
863 } 937 }
864 938
865 void NTPSnippetsService::FinishInitialization() { 939 void NTPSnippetsService::FinishInitialization() {
866 if (nuke_when_initialized_) { 940 if (nuke_when_initialized_) {
867 // We nuke here in addition to EnterStateReady, so that it happens even if 941 // We nuke here in addition to EnterStateReady, so that it happens even if
868 // we enter the DISABLED state below. 942 // we enter the DISABLED state below.
869 NukeAllSnippets(); 943 NukeAllSnippets();
870 nuke_when_initialized_ = false; 944 nuke_when_initialized_ = false;
871 } 945 }
872 946
873 snippets_fetcher_->SetCallback(
874 base::Bind(&NTPSnippetsService::OnFetchFinished, base::Unretained(this)));
875
876 // |image_fetcher_| can be null in tests. 947 // |image_fetcher_| can be null in tests.
877 if (image_fetcher_) { 948 if (image_fetcher_) {
878 image_fetcher_->SetImageFetcherDelegate(this); 949 image_fetcher_->SetImageFetcherDelegate(this);
879 image_fetcher_->SetDataUseServiceName( 950 image_fetcher_->SetDataUseServiceName(
880 data_use_measurement::DataUseUserData::NTP_SNIPPETS); 951 data_use_measurement::DataUseUserData::NTP_SNIPPETS);
881 } 952 }
882 953
883 // Note: Initializing the status service will run the callback right away with 954 // Note: Initializing the status service will run the callback right away with
884 // the current state. 955 // the current state.
885 snippets_status_service_->Init(base::Bind( 956 snippets_status_service_->Init(base::Bind(
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
966 state_ = State::ERROR_OCCURRED; 1037 state_ = State::ERROR_OCCURRED;
967 EnterStateError(); 1038 EnterStateError();
968 break; 1039 break;
969 } 1040 }
970 1041
971 // Schedule or un-schedule background fetching after each state change. 1042 // Schedule or un-schedule background fetching after each state change.
972 RescheduleFetching(false); 1043 RescheduleFetching(false);
973 } 1044 }
974 1045
975 void NTPSnippetsService::NotifyNewSuggestions(Category category) { 1046 void NTPSnippetsService::NotifyNewSuggestions(Category category) {
1047 NotifyNewSuggestionsOrInvokeCallback(category, NullCallback());
1048 }
1049
1050 void NTPSnippetsService::NotifyNewSuggestionsOrInvokeCallback(
1051 Category category,
1052 FetchedMoreCallback fetched_more_callback) {
976 DCHECK(base::ContainsKey(categories_, category)); 1053 DCHECK(base::ContainsKey(categories_, category));
977 const CategoryContent& content = categories_[category]; 1054 const CategoryContent& content = categories_[category];
978 DCHECK(IsCategoryStatusAvailable(content.status)); 1055 DCHECK(IsCategoryStatusAvailable(content.status));
979
980 std::vector<ContentSuggestion> result; 1056 std::vector<ContentSuggestion> result;
981 for (const std::unique_ptr<NTPSnippet>& snippet : content.snippets) { 1057 for (const std::unique_ptr<NTPSnippet>& snippet : content.snippets) {
982 // TODO(sfiera): if a snippet is not going to be displayed, move it 1058 // TODO(sfiera): if a snippet is not going to be displayed, move it
983 // directly to content.dismissed on fetch. Otherwise, we might prune 1059 // directly to content.dismissed on fetch. Otherwise, we might prune
984 // other snippets to get down to kMaxSnippetCount, only to hide one of the 1060 // other snippets to get down to kMaxSnippetCount, only to hide one of the
985 // incomplete ones we kept. 1061 // incomplete ones we kept.
986 if (!snippet->is_complete()) 1062 if (!snippet->is_complete())
987 continue; 1063 continue;
988 ContentSuggestion suggestion(category, snippet->id(), 1064 result.emplace_back(
989 snippet->best_source().url); 1065 ContentSuggestion::FromSnippet(category, snippet.get()));
990 suggestion.set_amp_url(snippet->best_source().amp_url);
991 suggestion.set_title(base::UTF8ToUTF16(snippet->title()));
992 suggestion.set_snippet_text(base::UTF8ToUTF16(snippet->snippet()));
993 suggestion.set_publish_date(snippet->publish_date());
994 suggestion.set_publisher_name(
995 base::UTF8ToUTF16(snippet->best_source().publisher_name));
996 suggestion.set_score(snippet->score());
997 result.emplace_back(std::move(suggestion));
998 } 1066 }
999 1067
1000 DVLOG(1) << "NotifyNewSuggestions(" << category << "): " << result.size() 1068 DVLOG(1) << "NotifyNewSuggestions(" << category << "): " << result.size()
1001 << " items."; 1069 << " items.";
1002 observer()->OnNewSuggestions(this, category, std::move(result)); 1070 if (fetched_more_callback.is_null()) {
1071 observer()->OnNewSuggestions(this, category, std::move(result));
1072 } else {
1073 fetched_more_callback.Run(std::move(result));
1074 }
1003 } 1075 }
1004 1076
1005 void NTPSnippetsService::UpdateCategoryStatus(Category category, 1077 void NTPSnippetsService::UpdateCategoryStatus(Category category,
1006 CategoryStatus status) { 1078 CategoryStatus status) {
1007 DCHECK(base::ContainsKey(categories_, category)); 1079 DCHECK(base::ContainsKey(categories_, category));
1008 CategoryContent& content = categories_[category]; 1080 CategoryContent& content = categories_[category];
1009 if (status == content.status) 1081 if (status == content.status)
1010 return; 1082 return;
1011 1083
1012 DVLOG(1) << "UpdateCategoryStatus(): " << category.id() << ": " 1084 DVLOG(1) << "UpdateCategoryStatus(): " << category.id() << ": "
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
1112 } 1184 }
1113 1185
1114 NTPSnippetsService::CategoryContent::CategoryContent() = default; 1186 NTPSnippetsService::CategoryContent::CategoryContent() = default;
1115 NTPSnippetsService::CategoryContent::CategoryContent(CategoryContent&&) = 1187 NTPSnippetsService::CategoryContent::CategoryContent(CategoryContent&&) =
1116 default; 1188 default;
1117 NTPSnippetsService::CategoryContent::~CategoryContent() = default; 1189 NTPSnippetsService::CategoryContent::~CategoryContent() = default;
1118 NTPSnippetsService::CategoryContent& NTPSnippetsService::CategoryContent:: 1190 NTPSnippetsService::CategoryContent& NTPSnippetsService::CategoryContent::
1119 operator=(CategoryContent&&) = default; 1191 operator=(CategoryContent&&) = default;
1120 1192
1121 } // namespace ntp_snippets 1193 } // namespace ntp_snippets
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698