Chromium Code Reviews| 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/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 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 235 void NTPSnippetsService::FetchSnippets(bool interactive_request) { | 235 void NTPSnippetsService::FetchSnippets(bool interactive_request) { |
| 236 if (ready()) | 236 if (ready()) |
| 237 FetchSnippetsFromHosts(std::set<std::string>(), interactive_request); | 237 FetchSnippetsFromHosts(std::set<std::string>(), interactive_request); |
| 238 else | 238 else |
| 239 fetch_when_ready_ = true; | 239 fetch_when_ready_ = true; |
| 240 } | 240 } |
| 241 | 241 |
| 242 void NTPSnippetsService::FetchSnippetsFromHosts( | 242 void NTPSnippetsService::FetchSnippetsFromHosts( |
| 243 const std::set<std::string>& hosts, | 243 const std::set<std::string>& hosts, |
| 244 bool interactive_request) { | 244 bool interactive_request) { |
| 245 FetchSnippetsFromHostsImpl(hosts, | |
| 246 interactive_request, | |
| 247 base::MakeUnique<ReplaceExistingSnippets>(this)); | |
| 248 } | |
| 249 | |
| 250 void NTPSnippetsService::FetchMore() { | |
| 251 FetchSnippetsFromHostsImpl(std::set<std::string>(), | |
| 252 /* interactive_request= */ true, | |
|
Marc Treib
2016/10/18 08:17:45
nit: misaligned
There's a few other formatting thi
fhorschig
2016/10/20 13:10:38
Done. Thank you!
| |
| 253 base::MakeUnique<AddNewSnippets>(this)); | |
| 254 } | |
| 255 | |
| 256 void NTPSnippetsService::FetchSnippetsFromHostsImpl( | |
| 257 const std::set<std::string>& hosts, | |
| 258 bool interactive_request, | |
| 259 std::unique_ptr<NewNTPSnippetsHandlingStrategy> strategy) { | |
| 245 if (!ready()) | 260 if (!ready()) |
| 246 return; | 261 return; |
| 247 | 262 |
| 248 // Empty categories are marked as loading; others are unchanged. | 263 MarkEmptyCategoriesAsLoading(); |
| 264 | |
| 265 std::set<std::string> excluded_ids; | |
| 266 strategy->CollectIdsToExclude(&excluded_ids); | |
| 267 | |
| 268 snippets_fetcher_->SetCallback( | |
| 269 base::BindOnce(&NTPSnippetsService::OnFetchFinished, | |
| 270 base::Unretained(this), | |
| 271 std::move(strategy))); | |
| 272 | |
| 273 snippets_fetcher_->FetchSnippetsFromHosts(hosts, application_language_code_, | |
| 274 excluded_ids, kMaxSnippetCount, | |
| 275 interactive_request); | |
| 276 } | |
| 277 | |
| 278 void NTPSnippetsService::MarkEmptyCategoriesAsLoading() { | |
| 249 for (const auto& item : categories_) { | 279 for (const auto& item : categories_) { |
| 250 Category category = item.first; | 280 Category category = item.first; |
| 251 const CategoryContent& content = item.second; | 281 const CategoryContent& content = item.second; |
| 252 if (content.snippets.empty()) | 282 if (content.snippets.empty()) |
| 253 UpdateCategoryStatus(category, CategoryStatus::AVAILABLE_LOADING); | 283 UpdateCategoryStatus(category, CategoryStatus::AVAILABLE_LOADING); |
| 254 } | 284 } |
| 255 | |
| 256 std::set<std::string> excluded_ids; | |
| 257 for (const auto& item : categories_) { | |
| 258 const CategoryContent& content = item.second; | |
| 259 for (const auto& snippet : content.dismissed) | |
| 260 excluded_ids.insert(snippet->id()); | |
| 261 } | |
| 262 snippets_fetcher_->FetchSnippetsFromHosts(hosts, application_language_code_, | |
| 263 excluded_ids, kMaxSnippetCount, | |
| 264 interactive_request); | |
| 265 } | 285 } |
| 266 | 286 |
| 267 void NTPSnippetsService::RescheduleFetching(bool force) { | 287 void NTPSnippetsService::RescheduleFetching(bool force) { |
| 268 // The scheduler only exists on Android so far, it's null on other platforms. | 288 // The scheduler only exists on Android so far, it's null on other platforms. |
| 269 if (!scheduler_) | 289 if (!scheduler_) |
| 270 return; | 290 return; |
| 271 | 291 |
| 272 if (ready()) { | 292 if (ready()) { |
| 273 base::TimeDelta old_interval_wifi = | 293 base::TimeDelta old_interval_wifi = |
| 274 base::TimeDelta::FromInternalValue(pref_service_->GetInt64( | 294 base::TimeDelta::FromInternalValue(pref_service_->GetInt64( |
| (...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 513 ClearOrphanedImages(); | 533 ClearOrphanedImages(); |
| 514 FinishInitialization(); | 534 FinishInitialization(); |
| 515 } | 535 } |
| 516 | 536 |
| 517 void NTPSnippetsService::OnDatabaseError() { | 537 void NTPSnippetsService::OnDatabaseError() { |
| 518 EnterState(State::ERROR_OCCURRED); | 538 EnterState(State::ERROR_OCCURRED); |
| 519 UpdateAllCategoryStatus(CategoryStatus::LOADING_ERROR); | 539 UpdateAllCategoryStatus(CategoryStatus::LOADING_ERROR); |
| 520 } | 540 } |
| 521 | 541 |
| 522 void NTPSnippetsService::OnFetchFinished( | 542 void NTPSnippetsService::OnFetchFinished( |
| 543 std::unique_ptr<NewNTPSnippetsHandlingStrategy> strategy, | |
| 523 NTPSnippetsFetcher::OptionalFetchedCategories fetched_categories) { | 544 NTPSnippetsFetcher::OptionalFetchedCategories fetched_categories) { |
| 524 if (!ready()) | 545 if (!ready()) |
| 525 return; | 546 return; |
| 526 | 547 |
| 527 // Mark all categories as not provided by the server in the latest fetch. The | 548 // Mark all categories as not provided by the server in the latest fetch. The |
| 528 // ones we got will be marked again below. | 549 // ones we got will be marked again below. |
| 529 for (auto& item : categories_) { | 550 for (auto& item : categories_) { |
| 530 CategoryContent* content = &item.second; | 551 CategoryContent* content = &item.second; |
| 531 content->provided_by_server = false; | 552 content->provided_by_server = false; |
| 532 } | 553 } |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 557 categories_[category].provided_by_server = true; | 578 categories_[category].provided_by_server = true; |
| 558 | 579 |
| 559 // TODO(tschumann): Remove this histogram once we only talk to the content | 580 // TODO(tschumann): Remove this histogram once we only talk to the content |
| 560 // suggestions cloud backend. | 581 // suggestions cloud backend. |
| 561 if (category == articles_category_) { | 582 if (category == articles_category_) { |
| 562 UMA_HISTOGRAM_SPARSE_SLOWLY( | 583 UMA_HISTOGRAM_SPARSE_SLOWLY( |
| 563 "NewTabPage.Snippets.NumArticlesFetched", | 584 "NewTabPage.Snippets.NumArticlesFetched", |
| 564 std::min(fetched_category.snippets.size(), | 585 std::min(fetched_category.snippets.size(), |
| 565 static_cast<size_t>(kMaxSnippetCount + 1))); | 586 static_cast<size_t>(kMaxSnippetCount + 1))); |
| 566 } | 587 } |
| 567 ReplaceSnippets(category, std::move(fetched_category.snippets)); | 588 StoreSnippets(category, |
| 589 std::move(fetched_category.snippets), | |
| 590 strategy.get()); | |
| 568 } | 591 } |
| 569 } | 592 } |
| 570 | 593 |
| 571 // We might have gotten new categories (or updated the titles of existing | 594 // We might have gotten new categories (or updated the titles of existing |
| 572 // ones), so update the pref. | 595 // ones), so update the pref. |
| 573 StoreCategoriesToPrefs(); | 596 StoreCategoriesToPrefs(); |
| 574 | 597 |
| 575 for (const auto& item : categories_) { | 598 for (const auto& item : categories_) { |
| 576 Category category = item.first; | 599 Category category = item.first; |
| 577 UpdateCategoryStatus(category, CategoryStatus::AVAILABLE); | 600 UpdateCategoryStatus(category, CategoryStatus::AVAILABLE); |
| 578 } | 601 } |
| 579 | 602 |
| 580 // TODO(sfiera): equivalent metrics for non-articles. | 603 // TODO(sfiera): equivalent metrics for non-articles. |
| 581 const CategoryContent& content = categories_[articles_category_]; | 604 const CategoryContent& content = categories_[articles_category_]; |
| 582 UMA_HISTOGRAM_SPARSE_SLOWLY("NewTabPage.Snippets.NumArticles", | 605 UMA_HISTOGRAM_SPARSE_SLOWLY("NewTabPage.Snippets.NumArticles", |
| 583 content.snippets.size()); | 606 content.snippets.size()); |
| 584 if (content.snippets.empty() && !content.dismissed.empty()) { | 607 if (content.snippets.empty() && !content.dismissed.empty()) { |
| 585 UMA_HISTOGRAM_COUNTS("NewTabPage.Snippets.NumArticlesZeroDueToDiscarded", | 608 UMA_HISTOGRAM_COUNTS("NewTabPage.Snippets.NumArticlesZeroDueToDiscarded", |
| 586 content.dismissed.size()); | 609 content.dismissed.size()); |
| 587 } | 610 } |
| 588 | 611 |
| 589 // TODO(sfiera): notify only when a category changed above. | 612 // TODO(sfiera): notify only when a category changed above. |
| 590 NotifyNewSuggestions(); | 613 strategy->NotifySuggestions(); |
| 591 | 614 |
| 592 // Reschedule after a successful fetch. This resets all currently scheduled | 615 // Reschedule after a successful fetch. This resets all currently scheduled |
| 593 // fetches, to make sure the fallback interval triggers only if no wifi fetch | 616 // fetches, to make sure the fallback interval triggers only if no wifi fetch |
| 594 // succeeded, and also that we don't do a background fetch immediately after | 617 // succeeded, and also that we don't do a background fetch immediately after |
| 595 // a user-initiated one. | 618 // a user-initiated one. |
| 596 if (fetched_categories) | 619 if (fetched_categories) |
| 597 RescheduleFetching(true); | 620 RescheduleFetching(true); |
| 598 } | 621 } |
| 599 | 622 |
| 600 void NTPSnippetsService::ArchiveSnippets(Category category, | 623 void NTPSnippetsService::ArchiveSnippets(Category category, |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 614 if (content->archived.size() > kMaxArchivedSnippetCount) { | 637 if (content->archived.size() > kMaxArchivedSnippetCount) { |
| 615 NTPSnippet::PtrVector to_delete( | 638 NTPSnippet::PtrVector to_delete( |
| 616 std::make_move_iterator(content->archived.begin() + | 639 std::make_move_iterator(content->archived.begin() + |
| 617 kMaxArchivedSnippetCount), | 640 kMaxArchivedSnippetCount), |
| 618 std::make_move_iterator(content->archived.end())); | 641 std::make_move_iterator(content->archived.end())); |
| 619 content->archived.resize(kMaxArchivedSnippetCount); | 642 content->archived.resize(kMaxArchivedSnippetCount); |
| 620 database_->DeleteImages(GetSnippetIDVector(to_delete)); | 643 database_->DeleteImages(GetSnippetIDVector(to_delete)); |
| 621 } | 644 } |
| 622 } | 645 } |
| 623 | 646 |
| 624 void NTPSnippetsService::ReplaceSnippets(Category category, | 647 void NTPSnippetsService::AssignExpiryDates(NTPSnippet::PtrVector* snippets) { |
|
Marc Treib
2016/10/18 08:17:45
nit: this sets both publish and expiry dates. Also
fhorschig
2016/10/20 13:10:38
Done.
| |
| 625 NTPSnippet::PtrVector new_snippets) { | 648 for (std::unique_ptr<NTPSnippet>& snippet : *snippets) { |
| 626 DCHECK(ready()); | |
| 627 CategoryContent* content = &categories_[category]; | |
| 628 | |
| 629 // Remove new snippets that have been dismissed. | |
| 630 EraseMatchingSnippets(&new_snippets, content->dismissed); | |
| 631 | |
| 632 // Fill in default publish/expiry dates where required. | |
| 633 for (std::unique_ptr<NTPSnippet>& snippet : new_snippets) { | |
| 634 if (snippet->publish_date().is_null()) | 649 if (snippet->publish_date().is_null()) |
| 635 snippet->set_publish_date(base::Time::Now()); | 650 snippet->set_publish_date(base::Time::Now()); |
| 636 if (snippet->expiry_date().is_null()) { | 651 if (snippet->expiry_date().is_null()) { |
| 637 snippet->set_expiry_date( | 652 snippet->set_expiry_date( |
| 638 snippet->publish_date() + | 653 snippet->publish_date() + |
| 639 base::TimeDelta::FromMinutes(kDefaultExpiryTimeMins)); | 654 base::TimeDelta::FromMinutes(kDefaultExpiryTimeMins)); |
| 640 } | 655 } |
| 641 } | 656 } |
| 657 } | |
| 642 | 658 |
| 643 if (!base::CommandLine::ForCurrentProcess()->HasSwitch( | 659 void NTPSnippetsService::AddIncompleteSnippets( |
|
Marc Treib
2016/10/18 08:17:45
This has exactly the wrong name - it *removes* inc
fhorschig
2016/10/20 13:10:38
Done.
| |
| 644 switches::kAddIncompleteSnippets)) { | 660 NTPSnippet::PtrVector* snippets) { |
| 645 int num_new_snippets = new_snippets.size(); | 661 if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 646 // Remove snippets that do not have all the info we need to display it to | 662 switches::kAddIncompleteSnippets)) |
| 647 // the user. | 663 return; |
|
Marc Treib
2016/10/18 08:17:45
nit: braces if either the condition or the body do
fhorschig
2016/10/20 13:10:38
Done.
| |
| 648 new_snippets.erase( | 664 |
| 649 std::remove_if(new_snippets.begin(), new_snippets.end(), | 665 int num_snippets = snippets->size(); |
| 650 [](const std::unique_ptr<NTPSnippet>& snippet) { | 666 // Remove snippets that do not have all the info we need to display it to |
| 651 return !snippet->is_complete(); | 667 // the user. |
| 652 }), | 668 snippets->erase( |
| 653 new_snippets.end()); | 669 std::remove_if(snippets->begin(), snippets->end(), |
| 654 int num_snippets_dismissed = num_new_snippets - new_snippets.size(); | 670 [](const std::unique_ptr<NTPSnippet>& snippet) { |
| 655 UMA_HISTOGRAM_BOOLEAN("NewTabPage.Snippets.IncompleteSnippetsAfterFetch", | 671 return !snippet->is_complete(); |
| 656 num_snippets_dismissed > 0); | 672 }), |
| 657 if (num_snippets_dismissed > 0) { | 673 snippets->end()); |
| 658 UMA_HISTOGRAM_SPARSE_SLOWLY("NewTabPage.Snippets.NumIncompleteSnippets", | 674 int num_snippets_dismissed = num_snippets - snippets->size(); |
| 659 num_snippets_dismissed); | 675 UMA_HISTOGRAM_BOOLEAN("NewTabPage.Snippets.IncompleteSnippetsAfterFetch", |
| 660 } | 676 num_snippets_dismissed > 0); |
| 677 if (num_snippets_dismissed > 0) { | |
| 678 UMA_HISTOGRAM_SPARSE_SLOWLY("NewTabPage.Snippets.NumIncompleteSnippets", | |
| 679 num_snippets_dismissed); | |
| 661 } | 680 } |
| 681 } | |
| 682 | |
| 683 void NTPSnippetsService::StoreSnippets( | |
| 684 const Category& category, | |
| 685 NTPSnippet::PtrVector new_snippets, | |
| 686 NewNTPSnippetsHandlingStrategy* strategy) { | |
| 687 DCHECK(ready()); | |
| 688 CategoryContent* content = &categories_[category]; | |
| 689 | |
| 690 // Remove new snippets that have been dismissed. | |
| 691 EraseMatchingSnippets(&new_snippets, content->dismissed); | |
| 692 | |
| 693 AssignExpiryDates(&new_snippets); | |
| 694 AddIncompleteSnippets(&new_snippets); | |
| 662 | 695 |
| 663 // Do not touch the current set of snippets if the newly fetched one is empty. | 696 // Do not touch the current set of snippets if the newly fetched one is empty. |
| 664 if (new_snippets.empty()) | 697 if (new_snippets.empty()) |
| 665 return; | 698 return; |
| 666 | 699 |
| 667 // It's entirely possible that the newly fetched snippets contain articles | 700 // It's entirely possible that the newly fetched snippets contain articles |
| 668 // that have been present before. | 701 // that have been present before. |
| 669 // Since archival removes snippets from the database (indexed by | 702 // Since archival removes snippets from the database (indexed by |
| 670 // snippet->id()), we need to make sure to only archive snippets that don't | 703 // snippet->id()), we need to make sure to only archive snippets that don't |
| 671 // appear with the same ID in the new suggestions (it's fine for additional | 704 // appear with the same ID in the new suggestions (it's fine for additional |
| 672 // IDs though). | 705 // IDs though). |
| 673 EraseByPrimaryID(&content->snippets, *GetSnippetIDVector(new_snippets)); | 706 EraseByPrimaryID(&content->snippets, *GetSnippetIDVector(new_snippets)); |
| 674 ArchiveSnippets(category, &content->snippets); | |
| 675 | 707 |
| 676 // Save new articles to the DB. | 708 // Save new articles to the DB. |
| 677 database_->SaveSnippets(new_snippets); | 709 database_->SaveSnippets(new_snippets); |
| 678 | 710 |
| 679 content->snippets = std::move(new_snippets); | 711 strategy->SaveNewSnippets(category, std::move(new_snippets)); |
| 680 } | 712 } |
| 681 | 713 |
| 682 void NTPSnippetsService::ClearExpiredDismissedSnippets() { | 714 void NTPSnippetsService::ClearExpiredDismissedSnippets() { |
| 683 std::vector<Category> categories_to_erase; | 715 std::vector<Category> categories_to_erase; |
| 684 | 716 |
| 685 const base::Time now = base::Time::Now(); | 717 const base::Time now = base::Time::Now(); |
| 686 | 718 |
| 687 for (auto& item : categories_) { | 719 for (auto& item : categories_) { |
| 688 Category category = item.first; | 720 Category category = item.first; |
| 689 CategoryContent* content = &item.second; | 721 CategoryContent* content = &item.second; |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 855 } | 887 } |
| 856 | 888 |
| 857 void NTPSnippetsService::FinishInitialization() { | 889 void NTPSnippetsService::FinishInitialization() { |
| 858 if (nuke_when_initialized_) { | 890 if (nuke_when_initialized_) { |
| 859 // We nuke here in addition to EnterStateReady, so that it happens even if | 891 // We nuke here in addition to EnterStateReady, so that it happens even if |
| 860 // we enter the DISABLED state below. | 892 // we enter the DISABLED state below. |
| 861 NukeAllSnippets(); | 893 NukeAllSnippets(); |
| 862 nuke_when_initialized_ = false; | 894 nuke_when_initialized_ = false; |
| 863 } | 895 } |
| 864 | 896 |
| 865 snippets_fetcher_->SetCallback( | |
| 866 base::Bind(&NTPSnippetsService::OnFetchFinished, base::Unretained(this))); | |
| 867 | |
| 868 // |image_fetcher_| can be null in tests. | 897 // |image_fetcher_| can be null in tests. |
| 869 if (image_fetcher_) { | 898 if (image_fetcher_) { |
| 870 image_fetcher_->SetImageFetcherDelegate(this); | 899 image_fetcher_->SetImageFetcherDelegate(this); |
| 871 image_fetcher_->SetDataUseServiceName( | 900 image_fetcher_->SetDataUseServiceName( |
| 872 data_use_measurement::DataUseUserData::NTP_SNIPPETS); | 901 data_use_measurement::DataUseUserData::NTP_SNIPPETS); |
| 873 } | 902 } |
| 874 | 903 |
| 875 // Note: Initializing the status service will run the callback right away with | 904 // Note: Initializing the status service will run the callback right away with |
| 876 // the current state. | 905 // the current state. |
| 877 snippets_status_service_->Init(base::Bind( | 906 snippets_status_service_->Init(base::Bind( |
| (...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1101 pref_service_->Set(prefs::kRemoteSuggestionCategories, list); | 1130 pref_service_->Set(prefs::kRemoteSuggestionCategories, list); |
| 1102 } | 1131 } |
| 1103 | 1132 |
| 1104 NTPSnippetsService::CategoryContent::CategoryContent() = default; | 1133 NTPSnippetsService::CategoryContent::CategoryContent() = default; |
| 1105 NTPSnippetsService::CategoryContent::CategoryContent(CategoryContent&&) = | 1134 NTPSnippetsService::CategoryContent::CategoryContent(CategoryContent&&) = |
| 1106 default; | 1135 default; |
| 1107 NTPSnippetsService::CategoryContent::~CategoryContent() = default; | 1136 NTPSnippetsService::CategoryContent::~CategoryContent() = default; |
| 1108 NTPSnippetsService::CategoryContent& NTPSnippetsService::CategoryContent:: | 1137 NTPSnippetsService::CategoryContent& NTPSnippetsService::CategoryContent:: |
| 1109 operator=(CategoryContent&&) = default; | 1138 operator=(CategoryContent&&) = default; |
| 1110 | 1139 |
| 1140 //////////////////////////////////////////////////////////////////////////////// | |
| 1141 // Snippet Handling Strategy Implementations | |
| 1142 | |
| 1143 NTPSnippetsService:: | |
| 1144 NewNTPSnippetsHandlingStrategy::NewNTPSnippetsHandlingStrategy( | |
| 1145 NTPSnippetsService* service) | |
| 1146 : service_(service) {} | |
| 1147 | |
| 1148 NTPSnippetsService::ReplaceExistingSnippets::ReplaceExistingSnippets( | |
| 1149 NTPSnippetsService* service) | |
| 1150 : NewNTPSnippetsHandlingStrategy(service) {} | |
| 1151 | |
| 1152 void NTPSnippetsService::ReplaceExistingSnippets::CollectIdsToExclude( | |
| 1153 std::set<std::string>* ids) { | |
| 1154 for (const auto& item : service_->categories_) { | |
| 1155 const CategoryContent& content = item.second; | |
| 1156 for (const auto& snippet : content.dismissed) | |
| 1157 ids->insert(snippet->id()); | |
| 1158 } | |
| 1159 } | |
| 1160 | |
| 1161 void NTPSnippetsService::ReplaceExistingSnippets::SaveNewSnippets( | |
| 1162 const Category& category, | |
| 1163 NTPSnippet::PtrVector new_snippets) { | |
| 1164 CategoryContent* content = &service_->categories_[category]; | |
| 1165 service_->ArchiveSnippets(category, &content->snippets); | |
| 1166 content->snippets = std::move(new_snippets); | |
| 1167 } | |
| 1168 | |
| 1169 void NTPSnippetsService::ReplaceExistingSnippets::NotifySuggestions() { | |
| 1170 service_->NotifyNewSuggestions(); | |
| 1171 } | |
| 1172 | |
| 1173 NTPSnippetsService::AddNewSnippets::AddNewSnippets(NTPSnippetsService* service) | |
| 1174 : NewNTPSnippetsHandlingStrategy(service) {} | |
| 1175 | |
| 1176 void NTPSnippetsService::AddNewSnippets::CollectIdsToExclude( | |
| 1177 std::set<std::string>* ids) { | |
| 1178 for (const auto& item : service_->categories_) { | |
| 1179 const CategoryContent& content = item.second; | |
| 1180 for (const auto& snippet : content.dismissed) | |
| 1181 ids->insert(snippet->id()); | |
| 1182 for (const auto& snippet : content.archived) | |
| 1183 ids->insert(snippet->id()); | |
| 1184 for (const auto& snippet : content.snippets) | |
| 1185 ids->insert(snippet->id()); | |
| 1186 } | |
| 1187 } | |
| 1188 | |
| 1189 void NTPSnippetsService::AddNewSnippets::SaveNewSnippets( | |
| 1190 const Category& category, | |
| 1191 NTPSnippet::PtrVector new_snippets) { | |
| 1192 CategoryContent* content = &service_->categories_[category]; | |
| 1193 content->snippets.insert(content->snippets.end(), | |
| 1194 std::make_move_iterator(new_snippets.begin()), | |
| 1195 std::make_move_iterator(new_snippets.end())); | |
| 1196 } | |
| 1197 | |
| 1198 void NTPSnippetsService::AddNewSnippets::NotifySuggestions() { | |
| 1199 // TODO(fhorschig): Notify additional Suggestions only. | |
| 1200 service_->NotifyNewSuggestions(); | |
| 1201 } | |
| 1202 | |
| 1111 } // namespace ntp_snippets | 1203 } // namespace ntp_snippets |
| OLD | NEW |